Java中的Json反序列化/ w混合类型的Jackson,包含在一个数组中

时间:2016-12-01 16:11:19

标签: java json jackson json-deserialization

考虑以下json,从公共API获取:

 anyObject : {
     attributes: [ 
                    { 
                        "name":"anyName",
                        "value":"anyValue"
                    },
                    { 
                        "name":"anyName",
                        "value": 
                        {
                           "key":"anyKey",
                           "label":"anyLabel"
                        }
                     }
                 ]
              }

如您所见,有时值是一个简单的字符串,有时它是一个对象。是否有可能将这种类型的json结果反序列化为:

 class AnyObject {
     List<Attribute> attributes;
 }

 class Attribute {
     private String key;
     private String label;
 } 

我如何设计我的模型来涵盖这两种情况。那可能吗 ?

1 个答案:

答案 0 :(得分:3)

尽管如其他人所指出的那样难以管理,但你可以做你想做的事。添加自定义反序列化器来处理这种情况。我重写了你的bean,因为我觉得你的属性类有点误导。对象中的AttributeEntry类是该&#34;属性中的条目&#34;名单。 ValueObject是表示&#34; key&#34; /&#34; label&#34;的类。宾语。那些bean在下面,但这里是自定义反序列化器。我们的想法是检查JSON中的类型,并根据其&#34;值&#34;实例化相应的AttributeEntry。类型。

public class AttributeDeserializer extends JsonDeserializer<AttributeEntry> {
    @Override
    public AttributeEntry deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode root = p.readValueAsTree();
        String name = root.get("name").asText();
        if (root.get("value").isObject()) {
            // use your object mapper here, this is just an example
            ValueObject attribute = new ObjectMapper().readValue(root.get("value").asText(), ValueObject.class);
            return new AttributeEntry(name, attribute);
        } else if (root.get("value").isTextual()) {
            String stringValue = root.get("value").asText();
            return new AttributeEntry(name, stringValue);
        } else {
            return null; // or whatever
        }
    }
}

由于这种模糊的类型不便,您必须在整个代码库中进行一些类型检查。

然后,您可以将此自定义反序列化器添加到对象映射器中,如下所示:

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(AttributeEntry.class, new AttributeDeserializer());
objectMapper.registerModule(simpleModule);

这里是AttributeEntry:

public class AttributeEntry {
    private String name;
    private Object value;

    public AttributeEntry(String name, String value) {
        this.name = name;
        this.value = value;
    }

    public AttributeEntry(String name, ValueObject attributes) {
        this.name = name;
        this.value = attributes;
    }
    /* getters/setters */
}

这是ValueObject:

public class ValueObject {
    private String key;
    private String label;
    /* getters/setters */
}