Jackson 将 XML 与根序列化为抽象类

Luc*_*sta 5 java spring-boot jackson-dataformat-xml

我有一个应用程序,我需要在根级别使用不同的标签序列化 XML。

我使用以下场景实现了一个测试用例,通过相同的输入我得到了两个 xml。

<ClassTypeA>
    <fieldA>a</fieldA>
</ClassTypeA>
Run Code Online (Sandbox Code Playgroud)

<ClassTypeB>
    <fieldB>b</fieldB>
</ClassTypeB>
Run Code Online (Sandbox Code Playgroud)

为了序列化,我实现了这三个类:

<ClassTypeA>
    <fieldA>a</fieldA>
</ClassTypeA>
Run Code Online (Sandbox Code Playgroud)

在下面使用此测试会返回以下错误:

<ClassTypeB>
    <fieldB>b</fieldB>
</ClassTypeB>
Run Code Online (Sandbox Code Playgroud)
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'fieldA' as a subtype of `br.com.eletra.filemode.uaa.converter.TestXml`: known type ids = [ClassTypeA, ClassTypeB]
 at [Source: (StringReader); line: 2, column: 2]
Run Code Online (Sandbox Code Playgroud)

但是,在结构的开头插入任何标签时,序列化是成功的。

在此处输入图片说明

我用演绎类型的jackson 2.12做了另一个测试。


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = TestConcreteDisconnectXML.class, name = "ClassTypeA"),
        @JsonSubTypes.Type(value = TestConcreteConnectXML.class, name = "ClassTypeB"),
})
abstract class TestXml{

}

@Getter
@Setter
class TestConcreteDisconnectXML extends TestXml{
    private String fieldA;
}

@Getter
@Setter
class TestConcreteConnectXML extends TestXml{
    private String fieldB;
}

Run Code Online (Sandbox Code Playgroud)

但是抛出了一个没有详细信息的空错误:

java.lang.NullPointerException
    at com.fasterxml.jackson.dataformat.xml.util.StaxUtil.sanitizeXmlTypeName(StaxUtil.java:81)
    at com.fasterxml.jackson.dataformat.xml.XmlTypeResolverBuilder.typeProperty(XmlTypeResolverBuilder.java:45)
    at com.fasterxml.jackson.dataformat.xml.XmlTypeResolverBuilder.typeProperty(XmlTypeResolverBuilder.java:25)
    at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector._findTypeResolver(JacksonAnnotationIntrospector.java:1517)
    at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.findTypeResolver(JacksonAnnotationIntrospector.java:572)
    at com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair.findTypeResolver(AnnotationIntrospectorPair.java:236)
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findTypeDeserializer(BasicDeserializerFactory.java:1754)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:597)
    at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4731)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4592)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3546)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3514)
    at br.com.eletra.filemode.uaa.converter.XmlConvertTest.testDeserializeXML(XmlConvertTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at junit.framework.TestCase.runTest(TestCase.java:177)
    at junit.framework.TestCase.runBare(TestCase.java:142)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:130)
    at junit.framework.TestSuite.runTest(TestSuite.java:241)
    at junit.framework.TestSuite.run(TestSuite.java:236)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)


Process finished with exit code -1

Run Code Online (Sandbox Code Playgroud)

有什么建议可以实现这样的东西,而不在运行时插入标签?

Alb*_*lia 1

您可能会尝试使用DEDUCTION查找子类型,因此根标记名称无关紧要,唯一使用的是字段:

@JsonTypeInfo(use=Id.DEDUCTION, defaultImpl = DefaultClassToUse.class)
... 
Run Code Online (Sandbox Code Playgroud)