Zoso619
Zoso619

Reputation: 177

Java HashMap one of the <V> has a <K,V> and need to fetch the value by the key

I have an API response that gives the below result . The response Map has 3 <K,V>. and One of the content has another <K,V> in its value . My problem here is I need to fetch the value of "plan_id" which is a Key . this simply contains a Key and value

so far the code is

ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> map1
                = objectMapper.readValue(response, new TypeReference<Map<String,Object>>(){});
        logger.info("-----------"+map1.get("content"));

not sure how to convert the map1 to another map and fetch the value for plan_id. if any other short cut please let me know.

response map

Upvotes: 0

Views: 82

Answers (2)

R4N
R4N

Reputation: 2595

If you don't want to create model objects for your response (and nested objects) you could use object mapper to read read the value as a JsonNode and then either use get or a jsonPtrExpr to get the exact value you want. Here are a couple of examples of that:

Example Json:

{
  "map1" : {
    "headers" : {},
    "content" : {
      "account" : {},
      "email" : {},
      "plan_id" : {
        "target_key" : "target_value"
      }
    }
  }
}

JsonNode with get

    JsonNode outerNode = mapper.readValue(jsonStringContents, JsonNode.class);
    // JsonNode with get
    String targetValueWithGet = outerNode.get("map1").get("content").get("plan_id").get(
            "target_key").asText();
    System.out.println("JsonNode with get: " + targetValueWithGet);

JsonNode with jsonPtrExpr

    JsonNode outerNode = mapper.readValue(jsonStringContents, JsonNode.class);
    // JsonNode with jsonPtrExpr
    String targetValueWithJsonPtrExpr = outerNode.at("/map1/content/plan_id/target_key").asText();
    System.out.println("JsonNode with jsonPtrExpr: " + targetValueWithJsonPtrExpr);

The outputs are:

JsonNode with get: target_value
JsonNode with jsonPtrExpr: target_value

Links:

JsonNode get: https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/JsonNode.html#get(java.lang.String)

JsonNode at: https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/JsonNode.html#at(com.fasterxml.jackson.core.JsonPointer)

JsonPointer (expression passed into at): https://fasterxml.github.io/jackson-core/javadoc/2.7/com/fasterxml/jackson/core/JsonPointer.html

The at method will return a node with isMissingNode() == true if the path doesn't exist, so if you're unsure that the structure will always be the same from your response, you'll probably want to check that

This is from the documentation linked (for at):

Node that matches given JSON Pointer: if no match exists, will return a node for which isMissingNode() returns true.

When this occurs your asText will return null, so you'll want to handle that case (either by checking isMissingNode() before calling asText() or checking if asText() is null)

    JsonNode outerNode = mapper.readValue(jsonStringContents, JsonNode.class);
    JsonNode targetNode = outerNode.at("/incorrect/path");
    System.out.println("Is missing node = " + targetNode.isMissingNode());
    String textFromMissingNode = targetNode.asText();

Which outputs:

Is missing node = true
asText value after calling on missing node = 

Edit:

In both of the above examples, for brevity I left off the instantiation of ObjectMapper and reading the local json file (I just used a local json file for the example code here):

ObjectMapper mapper = new ObjectMapper();
// this should be wrapped in a try/catch (catching IOException) or the method should be marked as throw IOException
String jsonStringContents = Files.readString(Path.of(NestedMapping.class.getClassLoader().getResource("test.json").getPath()));

NestedMapping is my class in this example, I don't believe you'll be reading the json file from local resources, but if you are you'll want to switch that to your class.

Upvotes: 1

Reddi
Reddi

Reputation: 743

I have mocked some data you have provided as below.

Debug values

In order to retrieve the values for the "plan_id" key I do use this code.

for(var values : map.values()) {
    if(values.containsKey("plan_id")) {
        // return values for 'plan_id' key.
    }
}

Upvotes: 0

Related Questions