javajsonjacksondeserialization

How to deserialize a custom object that has a parameter string with escaped JSON and dynamic key into Java Object


I have a JSON as below

{
   "fixedKey1" : "value1",
   "fixedKey2" : "value2",
   "fixedKey3" : "{\"DYNAMICKEY\":{\"innerKey1\":\"innerVal1\",\"innerKey2\":\"innerVal1\"}}"
}

I'm interested to extract only the inner JSON key and values in the fixedKey3.

Notice that fixedKey3 is a complex string that has a dynamic key that I cannot control. It is different in each response so that can never be a fixed key parameter.

So far I've written the below code, doing trial and error with no success

Below is the outer class of the entire JSON

class Outer {
  String fixedKey1;

  String fixedKey2;

  @JsonProperty("fixedKey3")
  public void setFixedKey3(String input) {
      ObjectMapper mapper = new ObjectMapper();

      //NEED help here
      mapper.readValue(input, InnerData.class);
  }
}

Below is the inner class which is supposed to contain inner values data.

class InnerData {
   String innerKey1;

   String innerKey2;
}

I'll be very grateful if you can help me. Thanks in advance.


Solution

  • The first problem about your scenario is about the

    "fixedKey3" : "{ "DYNAMICKEY": { "innerKey1": "innerVal1", "innerKey2": "innerVal1 "}}"
    

    containing escaped double quotes: a first step to solve your question is using the readTree method and read the JsonNode obtained with asText to get rid of the escaped double quotes like below:

    JsonNode root = mapper.readTree(json);
    //s will contains {"DYNAMICKEY":{"innerKey1":"innerVal1","innerKey2":"innerVal1"}}
    String s = root.get("fixedKey3").asText();
    

    To obtain the "DYNAMICKEY" dynamic key you can use the fieldNames method and with the treeToValue method mapping the obtained JsonNode to one InnerData object as you expect:

    JsonNode dynamicKeyNode = mapper.readTree(s);
    String dynamicKey = dynamicKeyNode.fieldNames().next(); //<-- it will contains your dynamic key
    //mapping the {"innerKey1":"innerVal1","innerKey2":"innerVal1"} to InnerData
    InnerData innerData = mapper.treeToValue(dynamicKeyNode.get(dynamicKey), InnerData.class);
    

    Note: for simplicity in the InnerData class the fields innerKey1 and innerKey2 are public.