当前位置: 首页 > 知识库问答 >
问题:

杰克逊:继承和必需的属性

裴意
2023-03-14

我目前正在尝试使用能够处理多态性的jackson实现反序列化程序,也就是说,给定这两个类:

public abstract class Animal {
  private String name;
  private float weight;

  @JsonCreator
  protected Animal(@JsonProperty(value="name") String name, @JsonProperty(value="weight",required=true) int weight) {
      this.name=name;
      this.weight=weight;
  }
}

public class Dog extends Animal {
    private int barkVolume;

    @JsonCreator
    public Dog(String name,int weight, @JsonProperty(value="barkVolume",required=true) int barkVolume) {
        super(name, weight);
        this.barkVolume=barkVolume;
    }

}

反序列化器应该能够从json字符串推断和实例化正确的子类。

我使用自定义解串器模块,即唯一属性多态态序列化器(从 https://gist.github.com/robinhowlett/ce45e575197060b8392d)。此模块的配置如下:

UniquePropertyPolymorphicDeserializer<Animal> deserializer =
             new UniquePropertyPolymorphicDeserializer<Animal>(Animal.class);

        deserializer.register("barkVolume", Dog.class);

        SimpleModule module = new SimpleModule("UniquePropertyPolymorphicDeserializer");
        module.addDeserializer(Animal.class, deserializer);
        mapper.registerModule(module);

该模块向用户询问动物的每个子类的唯一属性。因此,当反序列化器找到一个带有barkVolume属性的json字符串时,它知道应该实例化一个Dog。

然而,我对json属性的规范有一个问题,因为子类不能继承父类中给定的属性。在Dog类中,我必须再次指定“name”和“weight”是json属性,即使这些属性已经在Animal类中指定:

public Dog(@JsonProperty(value="name") String name, @JsonProperty(value="weight",required=true) int weight, @JsonProperty(value="barkVolume",required=true) int barkVolume) {
        super(name, weight);
        this.barkVolume=barkVolume;
    }

否则,反序列化程序会生成一个错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `Animals.Dog`: Argument #0 has no property name, is not Injectable: can not use as Creator [constructor for Animals.Dog, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}]
 at [Source: UNKNOWN; line: -1, column: -1]

这个解决方案对我来说并不令人满意:

>

  • 每次我们要创建一个新的 Animal 子类时,我们必须在此类中指定名称和权重是 json 属性

    这很棘手,例如,在Animal类中,weight属性被标记为必需的,而在子类中,我们可以定义weight不是必需的属性。

    你知道从父类的属性“继承”的方法吗,这样可以避免每次在子类中指定相应的json属性?

    最好的问候,

    马蒂厄

  • 共有1个答案

    单修德
    2023-03-14

    我最终决定创建我自己的Deserializer(而不是UniqueProperty tyDeserializer),在其中我使用自省来获取父类的字段。它允许避免在子类中再次指定所需的json属性。

     类似资料:
    • 问题内容: 我在对象映射器上使用Jackson的readValue()方法从JSON文件读取并将其转换为我的Java对象。 例如。 我可以在MyTargetClass上设置任何注释以强制执行必需的属性吗?例如,如果我有一个具有ABC,DEF和GHI属性的JSON对象,而我的Json是以下内容 我希望它以某种方式失败,并且仅在readValue包含ABC,DEF和GHI时才能成功。 问题答案: Ja

    • 我在对象映射器上使用Jackson的readValue()方法从JSON文件中读取并将其转换为我的java对象。 如。 我可以在MyTargetClass上设置任何注释来强制执行所需的属性吗?例如,如果我有一个属性为ABC、DEF和GHI的JSON对象,我的JSON如下 我希望它以某种方式失败,并且只有在readValue上成功,如果它包含ABC、DEF和GHI。

    • 我如何告诉Jackson忽略JSON名称? 我有以下POJO: 当我有这样的东西: “ABCName”:“foo”,然后杰克逊没有认出它抛出错误。 它期望的是: “abcName”:“foo”。 代码: 输出:{"abcname":"Foo"} 然后我试着用@JsonProperty(“ABCName”)注释ABCName 在我注释并运行代码之后,我得到的是:{“ABCName”:“Foo”,“A

    • 首先,我不熟悉Jython。我正在寻找一种将python代码集成到Java项目中的方法。因此我正在调查Jython。 我正在尝试将一个 json 字符串转换为 Java 对象 - 在 python 中。 首先,我一直在努力让Jython找到我的java类。由于缺乏更优雅的解决方案,我可以通过简单地执行以下操作来向前迈进: 无论如何。。。 我正在尝试以下操作: 但是,在运行时,我收到以下错误: 我不

    • 我想使用Spring的RestTemplate plus Jackson来使用Web服务。我已经学习了几本教程,并且已经达到了创建DAO的目的。这是我获取所有域对象的方法: 但我的Web服务不会立即返回Station对象数组,而是以这种方式返回一个更具语义的表达式: 所以我的问题是,我不知道如何“告诉”RestTemplate在“stations”指示符之后立即解析对象列表,而不创建临时对象,这似

    • 问题内容: 可以同时使用Spring 和的注释,使用Jackson 和注释来修改Spring MVC控制器返回的JSON 吗? 当客户端请求的集合时,我想返回每个的最小版本,也许只是它的ID。然后,在随后的调用中,客户端可以使用该ID来请求具有所有属性的完整实例。 能够在Spring MVC控制器方法上指定它是理想的,因为调用的方法定义了客户端请求数据的上下文。 问题答案: 这个问题解决了! 跟随