Java 防止Jackson XML映射器将WSTXN添加到名称空间
将对象序列化为XML并使用为属性指定名称空间时Java 防止Jackson XML映射器将WSTXN添加到名称空间,java,xml,jackson,jackson-dataformat-xml,Java,Xml,Jackson,Jackson Dataformat Xml,将对象序列化为XML并使用为属性指定名称空间时 @JacksonXmlRootElement(命名空间=”http://...“” Jackson将在名称空间中附加或前置“wstxns1”。例如,假设我们有这些类: VtexSkuAttributeValues.java @JacksonXmlRootElement(localName = "listStockKeepingUnitName") public class VtexSkuAttributeValues { @Jackson
@JacksonXmlRootElement(命名空间=”http://...“”
Jackson将在名称空间中附加或前置“wstxns1”。例如,假设我们有这些类:
VtexSkuAttributeValues.java
@JacksonXmlRootElement(localName = "listStockKeepingUnitName")
public class VtexSkuAttributeValues {
@JacksonXmlProperty(localName = "StockKeepingUnitFieldNameDTO", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
@JacksonXmlElementWrapper(useWrapping = false)
private VtexSkuAttributeValue[] stockKeepingUnitFieldNameDTO;
public VtexSkuAttributeValue[] getStockKeepingUnitFieldNameDTO() {
return stockKeepingUnitFieldNameDTO;
}
public void setValues(VtexSkuAttributeValue[] values) {
this.stockKeepingUnitFieldNameDTO = values;
}
}
@JacksonXmlRootElement(localName = "StockKeepingUnitFieldNameDTO", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
public class VtexSkuAttributeValue {
private String fieldName;
private FieldValues fieldValues;
private int idSku;
public int getIdSku() {
return idSku;
}
public String getFieldName() {
return fieldName;
}
public FieldValues getFieldValues() {
return fieldValues;
}
public void setIdSku(int idSku) {
this.idSku = idSku;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public void setFieldValues(FieldValues fieldValues) {
this.fieldValues = fieldValues;
}
@JacksonXmlRootElement(localName = "fieldValues", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
public static class FieldValues {
@JacksonXmlProperty(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")
@JacksonXmlElementWrapper(useWrapping = false)
public String[] string;
public String[] getString() {
return string;
}
public void setValues(String[] values) {
this.string = values;
}
}
}
VtexSkuAttributeValue.java
@JacksonXmlRootElement(localName = "listStockKeepingUnitName")
public class VtexSkuAttributeValues {
@JacksonXmlProperty(localName = "StockKeepingUnitFieldNameDTO", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
@JacksonXmlElementWrapper(useWrapping = false)
private VtexSkuAttributeValue[] stockKeepingUnitFieldNameDTO;
public VtexSkuAttributeValue[] getStockKeepingUnitFieldNameDTO() {
return stockKeepingUnitFieldNameDTO;
}
public void setValues(VtexSkuAttributeValue[] values) {
this.stockKeepingUnitFieldNameDTO = values;
}
}
@JacksonXmlRootElement(localName = "StockKeepingUnitFieldNameDTO", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
public class VtexSkuAttributeValue {
private String fieldName;
private FieldValues fieldValues;
private int idSku;
public int getIdSku() {
return idSku;
}
public String getFieldName() {
return fieldName;
}
public FieldValues getFieldValues() {
return fieldValues;
}
public void setIdSku(int idSku) {
this.idSku = idSku;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public void setFieldValues(FieldValues fieldValues) {
this.fieldValues = fieldValues;
}
@JacksonXmlRootElement(localName = "fieldValues", namespace = "http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts")
public static class FieldValues {
@JacksonXmlProperty(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")
@JacksonXmlElementWrapper(useWrapping = false)
public String[] string;
public String[] getString() {
return string;
}
public void setValues(String[] values) {
this.string = values;
}
}
}
然后,我使用XmlMapper
序列化并获得:
<listStockKeepingUnitName>
<wstxns1:StockKeepingUnitFieldNameDTO xmlns:wstxns1="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>talle</fieldName>
<fieldValues>
<wstxns2:string xmlns:wstxns2="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6184</wstxns2:string>
</fieldValues>
<idSku>258645</idSku>
</wstxns1:StockKeepingUnitFieldNameDTO>
<wstxns3:StockKeepingUnitFieldNameDTO xmlns:wstxns3="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>color</fieldName>
<fieldValues>
<wstxns4:string xmlns:wstxns4="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6244</wstxns4:string>
</fieldValues>
<idSku>258645</idSku>
</wstxns3:StockKeepingUnitFieldNameDTO>
</listStockKeepingUnitName>
塔勒
6184
258645
颜色
6244
258645
即使这是有效的XML,我使用的web服务也不接受它。我调试了它,这是由于Jackson出于某种原因添加的标记中的wstxns
属性。
有没有办法阻止Jackson将其添加到标签中。我能想到的唯一解决办法是对生成的XML执行string.replaceAll,但这显然不理想。编写
XML
Jackson
使用javax.XML.stream.XMLStreamWriter
。您可以配置该类的实例,为名称空间定义自己的前缀,并根据需要设置默认前缀。为此,我们需要扩展com.fasterxml.jackson.dataformat.xml.XmlFactory
类,并重写一个创建XMLStreamWriter
实例的方法。示例实现如下所示:
class NamespaceXmlFactory extends XmlFactory {
private final String defaultNamespace;
private final Map<String, String> prefix2Namespace;
public NamespaceXmlFactory(String defaultNamespace, Map<String, String> prefix2Namespace) {
this.defaultNamespace = Objects.requireNonNull(defaultNamespace);
this.prefix2Namespace = Objects.requireNonNull(prefix2Namespace);
}
@Override
protected XMLStreamWriter _createXmlWriter(IOContext ctxt, Writer w) throws IOException {
XMLStreamWriter writer = super._createXmlWriter(ctxt, w);
try {
writer.setDefaultNamespace(defaultNamespace);
for (Map.Entry<String, String> e : prefix2Namespace.entrySet()) {
writer.setPrefix(e.getKey(), e.getValue());
}
} catch (XMLStreamException e) {
StaxUtil.throwAsGenerationException(e, null);
}
return writer;
}
}
并将其用于应该用作默认名称空间的每个类和字段。例如:
@JacksonXmlProperty(localName = "StockKeepingUnitFieldNameDTO", namespace = DEF_NMS)
对于不想更改其名称的属性,可以使用:
@JacksonXmlProperty(namespace = VtexSkuAttributeValues.DEF_NMS)
上面的代码打印一些随机数据:
<listStockKeepingUnitName>
<StockKeepingUnitFieldNameDTO xmlns="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>Name1</fieldName>
<fieldValues>
<a:string xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6184</a:string>
</fieldValues>
<idSku>123</idSku>
</StockKeepingUnitFieldNameDTO>
<StockKeepingUnitFieldNameDTO xmlns="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>Name1</fieldName>
<fieldValues>
<a:string xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6184</a:string>
</fieldValues>
<idSku>123</idSku>
</StockKeepingUnitFieldNameDTO>
</listStockKeepingUnitName>
名称1
6184
123
名称1
6184
123
如果这不是您想要的,您可以使用该代码并尝试其他可用于配置此实例的方法
使用版本
2.9.9
创建此示例Jackson
。编写XML
Jackson使用javax.XML.stream.XMLStreamWriter
。您可以配置该类的实例,为名称空间定义自己的前缀,并根据需要设置默认前缀。为此,我们需要扩展com.fasterxml.jackson.dataformat.xml.XmlFactory
类,并重写一个创建XMLStreamWriter
实例的方法。示例实现如下所示:
class NamespaceXmlFactory extends XmlFactory {
private final String defaultNamespace;
private final Map<String, String> prefix2Namespace;
public NamespaceXmlFactory(String defaultNamespace, Map<String, String> prefix2Namespace) {
this.defaultNamespace = Objects.requireNonNull(defaultNamespace);
this.prefix2Namespace = Objects.requireNonNull(prefix2Namespace);
}
@Override
protected XMLStreamWriter _createXmlWriter(IOContext ctxt, Writer w) throws IOException {
XMLStreamWriter writer = super._createXmlWriter(ctxt, w);
try {
writer.setDefaultNamespace(defaultNamespace);
for (Map.Entry<String, String> e : prefix2Namespace.entrySet()) {
writer.setPrefix(e.getKey(), e.getValue());
}
} catch (XMLStreamException e) {
StaxUtil.throwAsGenerationException(e, null);
}
return writer;
}
}
并将其用于应该用作默认名称空间的每个类和字段。例如:
@JacksonXmlProperty(localName = "StockKeepingUnitFieldNameDTO", namespace = DEF_NMS)
对于不想更改其名称的属性,可以使用:
@JacksonXmlProperty(namespace = VtexSkuAttributeValues.DEF_NMS)
上面的代码打印一些随机数据:
<listStockKeepingUnitName>
<StockKeepingUnitFieldNameDTO xmlns="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>Name1</fieldName>
<fieldValues>
<a:string xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6184</a:string>
</fieldValues>
<idSku>123</idSku>
</StockKeepingUnitFieldNameDTO>
<StockKeepingUnitFieldNameDTO xmlns="http://schemas.datacontract.org/2004/07/Vtex.Commerce.WebApps.AdminWcfService.Contracts">
<fieldName>Name1</fieldName>
<fieldValues>
<a:string xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">6184</a:string>
</fieldValues>
<idSku>123</idSku>
</StockKeepingUnitFieldNameDTO>
</listStockKeepingUnitName>
名称1
6184
123
名称1
6184
123
如果这不是您想要的,您可以使用该代码并尝试其他可用于配置此实例的方法
使用版本
2.9.9
创建此示例Jackson
。这似乎是缺少的部分。它允许您设置前缀和命名空间
static class NamespaceXmlFactory extends XmlFactory {
private final String defaultNamespace;
private final Map<String, String> prefix2Namespace;
public NamespaceXmlFactory(String defaultNamespace, Map<String, String> prefix2Namespace) {
this.defaultNamespace = Objects.requireNonNull(defaultNamespace);
this.prefix2Namespace = Objects.requireNonNull(prefix2Namespace);
}
@Override
protected XMLStreamWriter _createXmlWriter(IOContext ctxt, Writer w) throws IOException {
XMLStreamWriter2 writer = (XMLStreamWriter2)super._createXmlWriter(ctxt, w);
try {
writer.setDefaultNamespace(defaultNamespace);
writer.setPrefix("xsi", "http://www.w3.org/2001/XMLSchema-instance");
for (Map.Entry<String, String> e : prefix2Namespace.entrySet()) {
writer.setPrefix(e.getKey(), e.getValue());
}
} catch (XMLStreamException e) {
StaxUtil.throwAsGenerationException(e, null);
}
return writer;
}
}
创建以下输出:
仍在尝试解决如何将其改为xsi:type=“networkObjectGroupDTO” 这似乎是丢失的部分。它允许您设置前缀和命名空间
static class NamespaceXmlFactory extends XmlFactory {
private final String defaultNamespace;
private final Map<String, String> prefix2Namespace;
public NamespaceXmlFactory(String defaultNamespace, Map<String, String> prefix2Namespace) {
this.defaultNamespace = Objects.requireNonNull(defaultNamespace);
this.prefix2Namespace = Objects.requireNonNull(prefix2Namespace);
}
@Override
protected XMLStreamWriter _createXmlWriter(IOContext ctxt, Writer w) throws IOException {
XMLStreamWriter2 writer = (XMLStreamWriter2)super._createXmlWriter(ctxt, w);
try {
writer.setDefaultNamespace(defaultNamespace);
writer.setPrefix("xsi", "http://www.w3.org/2001/XMLSchema-instance");
for (Map.Entry<String, String> e : prefix2Namespace.entrySet()) {
writer.setPrefix(e.getKey(), e.getValue());
}
} catch (XMLStreamException e) {
StaxUtil.throwAsGenerationException(e, null);
}
return writer;
}
}
创建以下输出:
仍在尝试解决如何将其改为xsi:type=“networkObjectGroupDTO” 这些“wstxns属性”来自
JacksonXmlRootElement
注释中的名称空间
属性。如果省略名称空间
属性,您会得到所需的输出吗?@dnault我无法操作它,因为它是web服务所必需的。这些“wstxns属性”来自JacksonXmlRootElement
注释中的名称空间
属性。如果省略namespace
属性,您会得到所需的输出吗?@dnault我无法操作它,因为它是web服务所必需的。这是一个非常好的示例,展示了Jackson XML的内部工作原理,现在我觉得我应该更好地表达我的问题。有没有办法完全防止Jackson向名称空间添加前缀?如果我设置一个空字符串作为前缀,Jackson默认为wstxns
。如果我将它设置为null,我会得到NullPointerException
@Morgan,Jackson
只是其他库的包装器,在这种情况下,它只是其他库的包装器。但是,通常不能同时在全局范围中有多个默认命名空间。使用不带前缀的默认名称空间xmlns
。如果您希望始终使用xmlns
而不使用任何前缀,则需要在序列化期间更改默认名称空间,因此在每个级别上,无论何时需要名称空间,我们都需要将其设置为默认名称空间。我认为我的示例将允许您生成一个可接受的XML
@Morgan,看看,了解NamespaceContext
类以及如何使用它。看,这是一个非常好的例子,展示了Jackson XML的内部工作原理,现在我觉得我应该把我的问题写得更好。有没有办法完全防止Jackson向名称空间添加前缀?如果我设置一个空字符串作为前缀,Jackson默认为wstxns
。如果我将它设置为null,我会得到NullPointerException
@Morgan,Jackson
只是其他库的包装器,在这种情况下,它只是其他库的包装器。但是,通常不能同时在全局范围中有多个默认命名空间。使用不带前缀的默认名称空间xmlns
。如果您希望始终使用xmlns
而不使用任何前缀,则需要在序列化期间更改默认名称空间,因此在每个级别上,无论何时需要名称空间,我们都需要将其设置为默认名称空间。我认为我的示例将允许您生成一个可接受的XML
@Morgan,看看,阅读namespacecoxt
类,然后