Reputation: 1
I am working with a third-party service that has provided us with an XSD, and I use a maven plugin (maven-jaxb2-plugin) to generate the corresponding java classes.
Using the JAXB Unmarshaller, I can deserialize the responses from the third-party service. However, due to constraints on the target execution environment, I cannot use the JAXB Unmarshaller - so I settled on using Jackson (jackson-dataformat-xml). However, I cannot get Jackson to deserialize the responses from the third-party service. I have provided representative samples of the XSD, generated code, and usage code below.
What I have tried so far:
What I have not tried:
I suspect that Jackson does not like the nested xs:choice
tags, but I do not know for sure - I will investigate that soon and post my findings on here, if any.
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="element1">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="element1_1">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attribute1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="aa"/>
<xs:enumeration value="de"/>
<xs:enumeration value="en"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="attribute2" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:choice minOccurs="0">
<xs:element ref="element2"/>
<xs:element name="element1_2" type="xs:string"/>
</xs:choice>
<xs:element ref="element3" minOccurs="0"/>
<xs:element name="element1_3" type="xs:dateTime" minOccurs="0"/>
<xs:element name="element1_4" type="xs:string" nillable="true" minOccurs="0"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="element2">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="element4" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:complexType>
</xs:element>
...
</xs:schema>
JAXB Generated Class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"element1_1OrElement2OrElement1_2"
})
@XmlRootElement(name = "ContentObject")
public class Element1 {
@XmlElements({
@XmlElement(name = "element1_1", type = JAXBElement.class, required = false),
@XmlElement(name = "element2", type = Element2.class, required = false),
@XmlElement(name = "element1_2", type = JAXBElement.class, required = false),
@XmlElement(name = "element3", type = Element3.class, required = false),
@XmlElement(name = "element1_3", type = JAXBElement.class, required = false),
...
})
protected List<Object> element1_1OrElement2OrElement1_2;
...
public List<Object> getElement1_1OrElement2OrElement1_2() {
if (element1_1OrElement2OrElement1_2 == null) {
element1_1OrElement2OrElement1_2 = new ArrayList<Object>();
}
return this.element1_1OrElement2OrElement1_2;
}
...
}
JUnit Test: The CustomeDeserializer can be ignored - it did not make any difference.
package my.project.webservice;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.bind.JAXBElement;
import org.junit.Test;
import org.w3c.dom.Document;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.jaxb.XmlJaxbAnnotationIntrospector;
import my.project.converter.ConverterException;
import my.project.converter.DocumentToStringConverter;
import my.project.converter.InputStreamToDocumentConverter;
import my.project.jaxb.CustomSerializer;
import my.project.jaxb.JaxbElementMixin;
import my.project.generated.GeneratedClass;
public class JacksonMapperTest {
@Test
public void test() {
try {
SimpleModule module = new SimpleModule("customeSerializerModule", new Version(1, 0, 0, null));
module.addSerializer(JAXBElement.class, new CustomSerializer());
XmlMapper m = new XmlMapper();
m.setAnnotationIntrospector(new XmlJaxbAnnotationIntrospector (m.getTypeFactory()));
m.addMixIn(JAXBElement.class, JaxbElementMixin.class);
m.registerModule(module);
InputStream is = this.getClass().getResourceAsStream("/stubbed-response.xml");
Document doc = new InputStreamToDocumentConverter().convert(is);
String xml = new DocumentToStringConverter().convert(doc);
GeneratedClass c = m.readValue(xml, GeneratedClass.class);
} catch (ConverterException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Stack Trace:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "element2" (class my.project.models.xjb.Element1), not marked as ignorable (15 known properties: "element1_1OrElement2OrElement3", "element1_3", ...])
at [Source: java.io.StringReader@6b419da; line: 3, column: 39] (through reference chain: my.project.generated.Element1["element2"]->java.util.ArrayList[0]->my.project.generated.Element1["element2"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:817)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:954)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1315)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:249)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:109)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:240)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:212)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:523)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.findDeserializeAndSet(BeanPropertyMap.java:285)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:248)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:109)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576)
at my.project.webservice.JacksonMapperTest.test(JacksonMapperTest.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.executeTestMethod(JUnit4TestRunnerDecorator.java:131)
at mockit.integration.junit4.internal.JUnit4TestRunnerDecorator.invokeExplosively(JUnit4TestRunnerDecorator.java:71)
at mockit.integration.junit4.internal.MockFrameworkMethod.invokeExplosively(MockFrameworkMethod.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at mockit.internal.util.MethodReflection.invokeWithCheckedThrows(MethodReflection.java:112)
at mockit.internal.mockups.MockMethodBridge.callMock(MockMethodBridge.java:85)
at mockit.internal.mockups.MockMethodBridge.invoke(MockMethodBridge.java:44)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Upvotes: 0
Views: 1914
Reputation: 526
Use this:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Here example: http://wiki.fasterxml.com/JacksonHowToIgnoreUnknown
Upvotes: -1