根据父属性反序列化 json 子类型

Fed*_*zza 4 java json jackson spring-boot

我有一个带有动态attribute子项的 json,如下所示:

{  
  "label":"Some label",
  "attribute": {     <--- Dynamic attribute object
    "type": "TEXT",  <--- Field used to map `attribute` dynamic (inside child object)
    "languages":[
      {
          "language":"en_EN",
          "text":"do you approve?"
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

或者

{  
  "label":"Some label",
  "attribute": {
    "type": "NUMBER",
    "value: "10.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用@JsonSubTypes以下代码正确反序列化上面的 json:

{  
  "label":"Some label",
  "attribute": {     <--- Dynamic attribute object
    "type": "TEXT",  <--- Field used to map `attribute` dynamic (inside child object)
    "languages":[
      {
          "language":"en_EN",
          "text":"do you approve?"
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,我遇到的问题是我必须使用type属性对象内部的字段,并且我需要将类型移动到父对象。结束的 json 应该是这样的:

{  
  "type": "TEXT",  <--- Field used to map `attribute` dynamic (in parent object)
  "label":"Some label",
  "attribute": {   <--- Dynamic attribute object
    "languages":[
      {
          "language":"en_EN",
          "text":"do you approve?"
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

或者

{  
  "type": "NUMBER",
  "label":"Some label",
  "attribute": {
    "value: "10.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

我找不到任何方法来使用父字段(或 json 路径方式)来使用type动态子类型之外的属性。你知道我该怎么做吗?

Ken*_*n S 5

您可以通过添加include = As.EXTERNAL_PROPERTY到来实现这一点@JsonTypeInfo。您只需将注释移至该字段即可。

请参阅 JavaDoc 了解 EXTERNAL_PROPERTY:

包含机制类似于PROPERTY,不同之处在于属性包含在层次结构中的更高一级 [...]

这是一个例子:

@Data
class Field {
    private String label;
    private AttributeType attributeType;
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.EXTERNAL_PROPERTY, property = "attributeType")
    private Attribute attribute;
}

@Data
@JsonSubTypes({
        @JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
        @JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
abstract class Attribute {
    @Data
    public static class TextAttribute extends Attribute {
        List<Language> languages;
    }

    @Data
    public static class NumberAttribute extends Attribute {
        String value;
    }

    @Data
    public static class Language {
        private String text;
        private String language;
    }
}

enum AttributeType {
    NUMBER, TEXT;
}
Run Code Online (Sandbox Code Playgroud)