-1
I have an application and need to serialize an XML with different tags at the root.
I implemented a test case with the following password, through the same input I can insert two types of XML
<ClassTypeA>
<fieldA>a</fieldA>
</ClassTypeA>
and
<ClassTypeB>
<fieldB>b</fieldB>
</ClassTypeB>
To serialize them I implemented these three classes:
@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;
}
Using the test below the following error is obtained:
public void testDeserializeXML() throws Exception {
objectMapper = new XmlMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String message = "<ClassTypeA>\n" +
"\t<fieldA>a</fieldA>\n" +
"</ClassTypeA>";
TestXml cxml = this.objectMapper.readValue(message, TestXml.class);
message = "<ClassTypeB>\n" +
"\t<fieldB>b</fieldB>\n" +
"</ClassTypeB>";
cxml = this.objectMapper.readValue(message, TestXml.class);
}
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]
However, when I enter any tag at the beginning of the structure, the serialization is successful.
I performed another test with Jackson 2.12 and Jsontypeinfo as DEDUCTION.
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
@JsonSubTypes.Type(ClassTypeA.class),
@JsonSubTypes.Type(ClassTypeB.class),
@JsonSubTypes.Type(DefaultClass.class),
})
abstract class TestXml{
}
@NoArgsConstructor
@Getter
@Setter
class ClassTypeA extends TestXml{
private String fieldA;
}
@NoArgsConstructor
@Getter
@Setter
class ClassTypeB extends TestXml{
private String fieldB;
}
@NoArgsConstructor
@Getter
@Setter
class DefaultClass extends TestXml{
}
But a Nullexception error without many details is triggered:
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
Any suggestions to implement something like this without having to insert the tag at runtime?
Please edit the question to limit it to a specific problem with sufficient detail to identify an appropriate answer.
–
what was not clear? the problem is very well specified
– Lucas Costa