问题描述
如果一个类中有多个自定义XML序列化器(XMLStreamWriter
),则序列化失败.
If there are multiple custom XML Serializers (XMLStreamWriter
) in a class, serialization fails.
我有两个班级:CustomClass1
,CustomClass2
.有一个包装类TestJacksonXml1
.当我尝试序列化TestJacksonXml1
时,它将引发异常.
I have two classes: CustomClass1
, CustomClass2
. There is a wrapping class TestJacksonXml1
. When I am trying to serialize TestJacksonXml1
, it throws an exception.
CustomClass1
CustomClass1
class CustomClass1 {
int prop1;
public CustomClass1(int prop1) {
this.prop1 = prop1;
}
public int getProp1() {
return prop1;
}
static class CustomClass1Serializer extends StdSerializer<CustomClass1> {
public CustomClass1Serializer() { this(null); }
public CustomClass1Serializer(Class<CustomClass1> t) {
super(t);
}
@Override
public void serialize(CustomClass1 customClass1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
final ToXmlGenerator toXmlGenerator = (ToXmlGenerator) jsonGenerator;
final XMLStreamWriter staxWriter = (toXmlGenerator).getStaxWriter();
try {
staxWriter.writeStartElement("class1");
staxWriter.writeCharacters(String.valueOf(customClass1.prop1));
staxWriter.writeEndElement();
} catch (XMLStreamException e){
e.printStackTrace();
}
}
}
}
CustomClass2
CustomClass2
class CustomClass2 {
int prop2;
public CustomClass2(int prop2) {
this.prop2 = prop2;
}
public int getProp2() {
return prop2;
}
static class CustomClass2Serializer extends StdSerializer<CustomClass2> {
public CustomClass2Serializer() { this(null); }
public CustomClass2Serializer(Class<CustomClass2> t) {
super(t);
}
@Override
public void serialize(CustomClass2 customClass2, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
final ToXmlGenerator toXmlGenerator = (ToXmlGenerator) jsonGenerator;
final XMLStreamWriter staxWriter = (toXmlGenerator).getStaxWriter();
try {
staxWriter.writeStartElement("class2");
staxWriter.writeCharacters(String.valueOf(customClass2.prop2));
staxWriter.writeEndElement();
} catch (XMLStreamException e){
e.printStackTrace();
}
}
}
}
封闭类
public class TestJacksonXml1 {
@JsonSerialize(using = CustomClass1.CustomClass1Serializer.class)
CustomClass1 obj1;
@JsonSerialize(using = CustomClass2.CustomClass2Serializer.class)
CustomClass2 obj2;
public TestJacksonXml1(CustomClass1 obj1, CustomClass2 obj2) {
this.obj1 = obj1;
this.obj2 = obj2;
}
public CustomClass1 getObj1() {
return obj1;
}
public CustomClass2 getObj2() {
return obj2;
}
public static void main(String[] args) throws JsonProcessingException {
XmlMapper xmlMapper = new XmlMapper();
System.out.println(xmlMapper.writeValueAsString(new TestJacksonXml1(new CustomClass1(10), new CustomClass2(20))));
}
}
我得到的例外是
Exception in thread "main" com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1961)
at com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator.writeFieldName(ToXmlGenerator.java:435)
at com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator.writeFieldName(ToXmlGenerator.java:577)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:725)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:202)
at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializer.serialize(XmlBeanSerializer.java:117)
at com.fasterxml.jackson.dataformat.xml.ser.XmlSerializerProvider.serializeValue(XmlSerializerProvider.java:107)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3905)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3219)
at fk.reportsvc.common.TestJacksonXml1.main(TestJacksonXml1.java:39)
当我注释掉其中一个自定义序列化程序时,另一个工作.为什么会这样呢?
When I comment out one of the custom serializers, the other one works. Why is it so?
我们不是应该一次使用两个/多个自定义序列化程序(与XMLStreamWriter
一起使用)吗?
Shouldn't we use two/multiple custom serializers (with XMLStreamWriter
) at once?
如果我直接使用JsonGenerator
而不是XMLStreamWriter
,则可以一次使用两个自定义序列化程序.
If I use JsonGenerator
directly instead of XMLStreamWriter
, then I am able to use both custom serializers at once.
PS:我的实际业务类别包含许多字段,这些字段将转换为嵌套的XML元素和属性.因此,更喜欢直接使用XMLStreamWriter
.
PS: My actual business classes contain many fields that are to be converted into nested XML elements and attributes. Hence preferring XMLStreamWriter
directly over others.
推荐答案
更简单的方法是使用ToXmlGenerator
类中的方法.看一下: setNextName , writeRaw 和 writeRepeatedFieldName 方法.在您的情况下,实现可能如下所示:
Much simpler would be to use methods from ToXmlGenerator
class. Take a look at: setNextName, writeRaw and writeRepeatedFieldName methods. In your case, implementation could look like below:
class CustomClass2Serializer extends StdSerializer<CustomClass2> {
private final QName name = new QName("class2");
public CustomClass2Serializer() {
super(CustomClass2.class);
}
@Override
public void serialize(CustomClass2 customClass2, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
final ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
xmlGenerator.setNextName(name);
xmlGenerator.writeStartObject();
xmlGenerator.writeRaw(String.valueOf(customClass2.prop2));
xmlGenerator.writeRepeatedFieldName();
xmlGenerator.writeEndObject();
}
}
和:
class CustomClass1Serializer extends StdSerializer<CustomClass1> {
private final QName name = new QName("class1");
public CustomClass1Serializer() {
super(CustomClass1.class);
}
@Override
public void serialize(CustomClass1 customClass1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
final ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
xmlGenerator.setNextName(name);
xmlGenerator.writeStartObject();
xmlGenerator.writeRaw(String.valueOf(customClass1.prop1));
xmlGenerator.writeRepeatedFieldName();
xmlGenerator.writeEndObject();
}
}
生成的XML
应该如下所示:
<TestJacksonXml1>
<class1>10</class1>
<class2>20</class2>
</TestJacksonXml1>
您遇到的主要问题是要跳过CustomClass1
和CustomClass1
类的object
节点.为TestJacksonXml1
类实现序列化器会更简单:
Main problem in your case is you want to skip object
node for CustomClass1
and CustomClass1
classes. Much simpler would be implementing serialiser for TestJacksonXml1
class:
class TestJacksonXml1JsonSerializer extends JsonSerializer<TestJacksonXml1> {
@Override
public void serialize(TestJacksonXml1 value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("class1", String.valueOf(value.obj1.prop1));
gen.writeStringField("class2", String.valueOf(value.obj2.prop2));
gen.writeEndObject();
}
}
现在,TestJacksonXml1类应如下所示:
Now, TestJacksonXml1 class should look like below:
@JsonSerialize(using = TestJacksonXml1JsonSerializer.class)
class TestJacksonXml1 {
CustomClass1 obj1;
CustomClass2 obj2;
// getters, setters, etc
}
它应该生成相同的输出,但是易于实现.
It should generate the same output but is much easier to implement.
这篇关于多个Jackson XML自定义(XMLStreamWriter)序列化程序引发异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!