5

I am trying to unmarshall a json file in a way such that few properties of Json are mapped into a HashMap that is present in my model class.Rest of the properties are mapped to the respective fields of the class.Please find the Json below:

{
         "_id":2,
         "Name":"xyz",
         "Age":20,
         "MEMO_TEXT":"yyy",
         "MEMO_LINK":"zzz",
         "MEMO_DOB":"",
         "MEMO_USERNAME":"linie orange",
         "MEMO_CATEGORY":2,
         "MEMO_UID":"B82071415B07495F9DD02C152E4805EC"
      }

And here is the Model class to which I want to map this Json:

public class Model{

    private int                              _id;
    private String                           name;
    private int                              age
    private HashMap<String, String> columns;

    //Getters and Setter methods
}

So here, what i want is to get a map columns that contains keys "MEMO_TEXT","MEMO_LINK","MEMO_DOB","MEMO_USERNAME","MEMO_CATEGORY","MEMO_UID"

and rest of the properties in Json are mapped to their respective fields.

Is it possible to do this using ObjectMapper of Jackson Library?

Puneetr90
  • 199
  • 1
  • 6
  • 18

3 Answers3

10

You can use @JsonAnySetter to annotate a method to be called for "other" properties:

@Test
public void partial_binding() throws Exception {
    Model model = mapper.readValue(Resources.getResource("partial_binding.json"), Model.class);
    assertThat(model.name, equalTo("xyz"));
    assertThat(model.columns, hasEntry("MEMO_TEXT", "yyy"));
    assertThat(
            mapper.writeValueAsString(model),
            json(jsonObject()
                 .withProperty("Name", "xyz")
                 .withProperty("MEMO_TEXT", "yyy")
                 .withAnyOtherProperties()));
}

public static class Model {
    @JsonProperty
    private int _id;
    @JsonProperty("Name")
    private String name;
    @JsonProperty("Age")
    private int age;
    private HashMap<String, String> columns;

    @JsonAnyGetter
    public HashMap<String, String> getColumns() {
        return columns;
    }

    public void setColumns(HashMap<String, String> columns) {
        this.columns = columns;
    }

    @JsonAnySetter
    public void putColumn(String key, String value) {
        if (columns == null) columns = new HashMap<>();
        columns.put(key, value);
    }
}

Also, @JsonAnyGetter does "kind of the reverse", so this should serialize and deserialize the same way.

araqnid
  • 127,052
  • 24
  • 157
  • 134
  • @Puneetr90 glad to be of help. if you feel your question has been answered, click the "tick" mark next to the answer to mark it as "accepted". – araqnid May 11 '15 at 11:11
1

One of several ways to achieve what you want is to add a constructor:

@JsonCreator
public Model(Map<String, Object> fields) {
    this._id = (int) fields.remove("_id");
    this.name = (String) fields.remove("Name");
    this.age = (int) fields.remove("Age");
    this.columns = new HashMap<String, String>();
    for (Entry<String, Object> column : fields.entrySet()) {
        columns.put(column.getKey(), column.getValue().toString());
    }
}

Be aware that if you serialize it back to JSON the structure will be diffrent than the initial one.

Lukasz Wiktor
  • 19,644
  • 5
  • 69
  • 82
0

Try using a SerializerProvider. A SerializerProvider can modify the deserialization, enabling custom deserialization.

Amir Kost
  • 2,148
  • 1
  • 16
  • 30