minhal
minhal

Reputation: 21

Deserialization using Jackson Json where one of the keys is dynamic

I am fairly new to Jackson. I am trying to map the following json to a POJO using Jackson for deserialization.

 {
  "data": [
    {
      "customerName": "abc",
      "varaible_Key1": { 
        "p1": "text data",
        "p2": "textarea data",
         ........
      }
    },
   {
      "customerName": "bbc",
      "varaible_Key2": {
        "p1": "text",
        "p2": "textarea"
        ...... 
      }
    },
   {
      "customerName": "xyz",
      "varaible_Key3": {
        "p1": "xyz text",
        "p2": "xyz textarea"
        ...... 
      }
    }
   ///////more customername / variable_keys
  ]
}

The problem I am facing is with dynamic / variable keys in the json.

I have tried using @JsonAnySetter in the POJO as shown below.

public class Foo {

    @JsonProperty("customerName")
    private String name;

    private Map<String, DataObject> properties;

    @JsonAnyGetter
    public Map<String, DataObject> getProperties() {
        return properties;
    }

    @JsonAnySetter
    public void add(String key, DataObject value) {
        properties.put(key, value);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    } 
}

where DataObject contains the fields like p1,p2 and so on.

public class DataObject {

    @JsonProperty("p1")
    private String firstValue;

    @JsonProperty("p2")
    private String secondValue;

    @JsonProperty("p3")
    private String thirdValue;

    @JsonProperty("p4")
    private String fourthValue;

    public String getFirstValue() {
        return firstValue;
    }

    public void setFirstValue(String firstValue) {
        this.firstValue = firstValue;
    }

    public String getSecondValue() {
        return secondValue;
    }

    public void setSecondValue(String secondValue) {
        this.secondValue = secondValue;
    }

    public String getThirdValue() {
        return thirdValue;
    }

    public void setThirdValue(String thirdValue) {
        this.thirdValue = thirdValue;
    }

    public String getFourthValue() {
        return fourthValue;
    }

    public void setFourthValue(String fourthValue) {
        this.fourthValue = fourthValue;
    }
}

I keep getting the below error. Any help on this is appreciated.

com.fasterxml.jackson.databind.JsonMappingException: N/A (through reference chain: com.epic.customer.dto.DataField["data"]->java.util.ArrayList[0]-> com.epic.customer.dto.Foo["varaible_Key1"]) at com.fasterxml.jackson.databind.deser.SettableAnyProperty._throwAsIOE(SettableAnyProperty.java:214) at com.fasterxml.jackson.databind.deser.SettableAnyProperty.set(SettableAnyProperty.java:179) at com.fasterxml.jackson.databind.deser.SettableAnyProperty.deserializeAndSet(SettableAnyProperty.java:134) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1539) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)

Upvotes: 2

Views: 1085

Answers (2)

trilogy
trilogy

Reputation: 1795

I think you have to give it a hint on the type of object you want back:

ObjectMapper mapper = new ObjectMapper();
Map<String, DataObject>  test = mapper.readValue("Insert Data in here", mapper.getTypeFactory().constructMapLikeType(HashMap.class, String.class, DataObject.class));

Upvotes: 0

Bejond
Bejond

Reputation: 1198

You just need to create 2 setters, for specific property:

class Foo {

    private DataObject dataObject;

    public DataObject getDataObject() {
        return dataObject;
    }

    public void setVaraible_Key1(DataObject dataObject) {
        this.dataObject = dataObject;
    }

    public void setVaraible_Key2(DataObject dataObject) {
        this.dataObject = dataObject;
    }
}

Further usages refers here.

Upvotes: 0

Related Questions