【问题标题】:jackson JAXB annotations - inheritance mapping at the root elementjackson JAXB 注释 - 根元素的继承映射
【发布时间】:2015-04-10 20:45:06
【问题描述】:

我有以下带有 Jaxb 注释的类层次结构,包括在文档根元素处的继承:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ParentClass", propOrder = {
        "parentField"
})
public class ParentClass{
    @XmlElement(name = "ParentField")
    protected String parentField;

  getters and setters here
}

ChildAClass:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ChildAClass", propOrder = {
        "childAfield"
})
public class ChildAClass extends ParentClass{

    @XmlElement(name = "ChildAfield")
    protected String childAfield;

  getters and setters here
}

ChildB类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ChildBClass", propOrder = {
        "childBfield"
})
public class ChildBClass extends ParentClass{

    @XmlElement(name = "ChildBfield")
    protected String childBfield;

  getters and setters here
}

这是非常简单的类层次结构。比我有简单的测试,我序列化 ChildAClass 并尝试反序列化为 ParentClass。我希望propper类被反序列化并向上转换为ParentClass。我想这是一个有效的用例。

序列化文档如下,这里没什么特别的。

{
  "ChildAfield": "child A field",
  "ParentField": "parent from child A"
}

但是当我尝试反序列化时:

    mapper = new ObjectMapper();
    JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();
    mapper.registerModule(jaxbAnnotationModule);

    mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
    mapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, false);
    mapper.setSerializationInclusion(JsonInclude.Include.NON_
ParentClass parentClass = mapper.readValue(new File(PATH_TO_FILE), ParentClass.class);

我收到以下异常:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ChildAfield" (class inheritance.model.ParentClass), not marked as ignorable (one known property: "ParentField"])
 at [Source: src/test/resources/testfiles/json/inheritance.json; line: 2, column: 19] (through reference chain: inheritance.model.ParentClass["ChildAfield"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
    at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty( ...

我想这里缺少一些类型元数据,用于适当的类型推断和反序列化。我一直在寻找@JsonTypeInfo,但我仅限于 JAXB。我尝试了@XmlElements jaxb 注释,但无法使其工作。

谁能给个提示?

谢谢

【问题讨论】:

    标签: java json serialization jaxb jackson


    【解决方案1】:

    尝试查看@JsonTypeInfo 是否会起作用可能是最简单的方法,就像测试一样。如果是这样,那么请弄清楚如何使用 JAXB 注释获得等效项。

    这对于 Jackson 用户 google 组来说可能也是一个好问题。

    我注意到的一件事是,根值对于很多事情都是有问题的。我发现将 Root 值限制为简单的 POJO 很有帮助,并且永远不要在那里使用 List、Map,甚至是多态 POJO。原因是 Java 类型擦除对通过属性引用的其他值的影响要小得多,然后具有完整的泛型类型可用。 在这里进行重组可能会也可能不会,但我提到这一点是因为它有时可以解决手头的问题。

    【讨论】:

      【解决方案2】:

      我得出结论为什么这不起作用。继承结构确实匹配“格式良好的文档”,但在类型标记的情况下,文档将具有不同的根元素,具体取决于使用的子类。这可能可以通过使用自定义 XmlTypeAdapter 来解决。以下在我看来是最简单的方法。

      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "RootClass", propOrder = {
              "parentClass"
      })
      public class RootClass {
          @XmlElements({
                  @XmlElement(name = "ChildAClass", type = ChildAClass.class),
                  @XmlElement(name = "ChildBClass", type = ChildBClass.class)
          })
          protected ParentClass parentClass;
      
       ... getters and setters
      }
      
      
      
      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "ParentClass", propOrder = {
              "parentField"
      })
      public class ParentClass{
          @XmlElement(name = "ParentField")
          protected String parentField;
      
       ... getters and setters
      }
      
      
      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "ChildAClass", propOrder = {
              "childAfield"
      })
      public class ChildAClass extends ParentClass{
      
          @XmlElement(name = "ChildAfield")
          protected String childAfield;
      
       ... getters and setters
      }
      
      
      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "ChildBClass", propOrder = {
              "childBfield"
      })
      public class ChildBClass extends ParentClass{
      
          @XmlElement(name = "ChildBfield")
          protected String childBfield;
      
       ... getters and setters
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        相关资源
        最近更新 更多