Reputation: 177
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.
Upvotes: 0
Views: 82
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:
{
"map1" : {
"headers" : {},
"content" : {
"account" : {},
"email" : {},
"plan_id" : {
"target_key" : "target_value"
}
}
}
}
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 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)
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
Reputation: 743
I have mocked some data you have provided as below.
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