【问题标题】:Deserializing json subtype based on parent property基于父属性反序列化json子类型
【发布时间】:2020-08-17 17:33:33
【问题描述】:

我有一个带有动态 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?"
      }
    ]
  }
}

或者

{  
  "label":"Some label",
  "attribute": {
    "type": "NUMBER",
    "value: "10.0"
  }
}

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

@Data
public class Field {
    private String label;
    private Attribute attribute;
}

@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
    @JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
})
public class Attribute {
    private AttributeType type;

    @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;
    }
}

但是,我遇到的问题是我必须使用属性对象内部的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?"
      }
    ]
  }
}

或者

{  
  "type": "NUMBER",
  "label":"Some label",
  "attribute": {
    "value: "10.0"
  }
}

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

【问题讨论】:

标签: java json spring-boot jackson


【解决方案1】:

您可以通过将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;
}

【讨论】:

  • 谢谢肯!这就成功了。我发布了一个同样有效的替代方案(根据您的回答)。
【解决方案2】:

如果接受的答案对其他人不起作用,我将其发布为替代方案:

@Data
public class Field {
    private String label;
    private AttributeType type;

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
    @JsonSubTypes({
        @JsonSubTypes.Type(value = Attribute.NumberAttribute.class, name = "NUMBER"),
        @JsonSubTypes.Type(value = Attribute.TextAttribute.class, name = "TEXT")
    })
    private Attribute attribute;
}

@Data
public 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;
    }
}

【讨论】:

    猜你喜欢
    • 2020-01-25
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    相关资源
    最近更新 更多