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

问题描述

我有一个带有动态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属性。你知道我该怎么做吗?

解决方法

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

如果其他人无法接受已接受的答案,我会以此为替代:

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