2015-02-06 76 views
0

我正在使用爲我們提供了XSD的第三方服務,並且使用maven插件(maven-jaxb2-plugin)生成相應的java類。Jackson在反序列化JAXB生成的類時拋出UnrecognizedPropertyException

使用JAXB Unmarshaller,我可以反序列化來自第三方服務的響應。但是,由於目標執行環境的限制,我無法使用JAXB Unmarshaller - 所以我決定使用Jackson(jackson-dataformat-xml)。但是,我無法讓傑克遜對第三方服務的反應進行反序列化。我已經提供了XSD的代表性示例,生成的代碼和使用代碼如下。

我迄今爲止嘗試:

我還沒有嘗試過:

  • 修改生成的代碼:我不想不得不重新做,如果XSD改變任何工作。如果我能確定它會起作用,這將是接下來的最後一招。
  • 每個XSD的手工編碼類別:同上,並且XSD對於很多對象來說相當大。這將是最後的手段。

我懷疑傑克遜不喜歡嵌套的xs:choice標籤,但我不確定 - 我會盡快調查並在此發佈我的發現,如果有的話。

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生成類:

@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測試: 的CustomeDeserializer可以忽略不計 - 它沒有任何區別。

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

} 

堆棧跟蹤:

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: [email protected]; 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) 
+0

選中此http://stackoverflow.com/questions/4486787/ jackson-with-json-unrecognized-field-not-marked-as-ignorable – 2015-02-06 07:21:25

回答

0

使用此:

objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

這裏例如:http://wiki.fasterxml.com/JacksonHowToIgnoreUnknown

+0

不幸的是,這並不奏效。反序列化的對象有很多空字段 - 我需要根據響應填充整個對象。 – 2015-02-06 14:43:44

+0

未知屬性是未在XSD中定義且未知的屬性。另外它的setter方法沒有定義。因此,這個問題是我的理解。對?所以如果這是正確的,那麼我認爲null的字段與XSD中未知的字段不同。 – 2015-02-06 17:14:48

+0

如果我沒有在我的問題中明確地說出來,我很抱歉。但是該屬性在XSD中定義,並且相應的setter在XJC生成的類中可用。但是,setter名稱的格式爲setAOrBOrC,因爲缺少的字段是XSD中xs:choice類型中的一個選項。另外,我可以使用JAXB反序列化。傑克遜不起作用。 – 2015-02-07 01:53:43

相關問題