繁体   English   中英

多个 Jackson XML 自定义 (XMLStreamWriter) 序列化程序抛出异常

[英]Multiple Jackson XML Custom (XMLStreamWriter) Serialisers throws Exception

如果一个类中有多个自定义 XML 序列化程序 ( XMLStreamWriter ),序列化将失败。

我有两个类: CustomClass1CustomClass2 有一个包装类TestJacksonXml1 当我尝试序列化TestJacksonXml1 ,它会引发异常。

自定义类1

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();
            }
        }
    }
}

自定义类2

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)

当我注释掉其中一个自定义序列化程序时,另一个可以工作。 为什么会这样?

我们不应该一次使用两个/多个自定义序列化程序(使用XMLStreamWriter )吗?

如果我直接使用JsonGenerator而不是XMLStreamWriter ,那么我可以同时使用两个自定义序列化程序。

PS:我的实际业务类包含许多要转换为嵌套 XML 元素和属性的字段。 因此,直接比其他人更喜欢XMLStreamWriter

使用ToXmlGenerator类中的方法要简单得多。 看看: setNextNamewriteRawwriteRepeatedFieldName方法。 在您的情况下,实现可能如下所示:

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>

您的情况的主要问题是您想跳过CustomClass1CustomClass1类的object节点。 TestJacksonXml1类实现序列化器要简单得多:

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 类应如下所示:

@JsonSerialize(using = TestJacksonXml1JsonSerializer.class)
class TestJacksonXml1 {

    CustomClass1 obj1;
    CustomClass2 obj2;
    // getters, setters, etc
}

它应该生成相同的输出,但更容易实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM