Search code examples
javajsonparsingjacksonfasterxml

Java - Deserialization Annotations with fasterXML and Jackson


Here's a simple example of working code to deserialize a string list using fasterXML/Jackson in the constructor:

private List<String> xyz;

@JsonCreator
public FooBar(@JsonProperty("blargs") List<String> xyz)
{
    this.xyz = xyz
}

So, the above code works fine, and it's my understanding of how to use Jackson to deserialize a json string like such: {"blargs":["one","two","three"]}

So, here's my question:

My input json now looks like such:

{"blargs":[
    {"fooId":888,"barVal":"tacos"},
    {"fooId":222,"barVal":"hamburgers"},
    {"fooId":444,"barVal":"underpants"}
  ]
}

...but I can't figure out how to annotate the constructor to deserialize the incoming json into my map where fooId and barVal become the key/value pairs.

Here's what I'm working with so far

private Map<Integer, String> xyz;

@JsonCreator
public FooBar(@JsonProperty("blargs") ????? Map<Integer, String> xyz)
{
    this.xyz = xyz
}

note: I am calling the constructors shown above as such:

ObjectMapper mapper = new ObjectMapper();
FooBar fooBar = mapper.readValue(jsonValue, FooBar.class);

Solution

  • You can write a custom deserializer:

    public static class XyzDeserializer extends JsonDeserializer<Map<Integer, String>> {
    
        @Override
        public Map<Integer, String> deserialize(JsonParser p,
                                                DeserializationContext ctxt) throws IOException {
            JsonNode rootNode = p.getCodec().readTree(p);
            Map<Integer, String> map = new HashMap<>();
            rootNode.forEach(n -> map.put(
                    n.get("fooId").intValue(),
                    n.get("barVal").asText()
            ));
            return map;
        }
    }
    

    And use it in this way:

    @JsonCreator
    public FooBar(
            @JsonProperty("blargs")
            @JsonDeserialize(using = XyzDeserializer.class) Map<Integer, String> xyz) {
        this.xyz = xyz;
    }