Json Deserialization in Java /w Jackson of mixed types, contained in one array

后端 未结 1 635
盖世英雄少女心
盖世英雄少女心 2021-01-22 20:13

Consider the following json, getting from an public API:

 anyObject : {
     attributes: [ 
                    { 
                        \"name\":\"anyName\",
         


        
相关标签:
1条回答
  • 2021-01-22 21:01

    Despite being hard to manage as others have pointed out, you can do what you want. Add a custom deserializer to handle this situation. I rewrote your beans because I felt your Attribute class was a bit misleading. The AttributeEntry class in the object that is an entry in that "attributes" list. The ValueObject is the class that represents that "key"/"label" object. Those beans are below, but here's the custom deserializer. The idea is to check the type in the JSON, and instantiate the appropriate AttributeEntry based on its "value" type.

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

    Because of this ambiguous type inconvenience, you will have to do some type checking throughout your code base.

    You can then add this custom deserializer to your object mapper like so:

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

    Here's the 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 */
    }
    

    Here's the ValueObject:

    public class ValueObject {
        private String key;
        private String label;
        /* getters/setters */
    }
    
    0 讨论(0)
提交回复
热议问题