Search code examples
javajacksonjackson-databind

How to deserialize complex JSON to java object


I need to deserialize JSON to java class.
I have JSON like the following:

{
  "data": {
    "text": "John" 
  },
  "fields":[
    {
      "id": "testId",
      "name": "fieldName",
      "options": {
        "color": "#000000",
        "required": true
      }
    },
    {
      "id": "testId",
      "name": "fieldName1",
      "options": {
        "color": "#000000",
        "required": false
      }
    }
  ]
}

and I need to deserialize this JSON (only "fields" section) to java class like the following:

public class Field {
    public final String id;
    public final String name;
    public final String color;
    public final boolean required;
}

and I need to get something like the following:

// The key is the id from field object (it can be the same in the multiple objects.)
Map<String, List<Field>> fields = objectMapper.readValue(json, Map<String, List<Field>>);

How can I do it using Jackson?


Solution

  • As long as jackson doesn't support @JsonWrapped, you have to use the following work around.

    First you need to create a custom class which contains the fields:

    public class Fields {
        public List<Field> fields;
    }
    

    Depending on your ObjectMapper configuration you have to add @JsonIgnoreProperties(ignoreUnknown = true) to the Fields class, to ignore any other properties.

    Next is that you have to define the nested Options class which is solely used temporarily:

    public class Options {
        public String color;
        public boolean required;
    }
    

    And at last add this constructor to your Field class:

    @JsonCreator
    public Field(@JsonProperty("id") String id, @JsonProperty("name") String name, @JsonProperty("options") Options options){
        this.id = id;
        this.name = name;
        this.color = options.color;
        this.required = options.required;
    }
    

    The @JsonCreator annotation indicates to jackson that this constructor needs to be used for the deserialization. Also the @JsonProperty annotations are required as arguments to constructors and methods are not preserved in the bytecode

    Then you can deserialize your json just like this:

    List<Field> fields = objectMapper.readValue(json, Fields.class).fields;