Jackson JsonNode

In this article, we will understand what is a JsonNode in Jackson library, how to get the key and value of a JsonNode, how to remove a node, how to update the value of a node with examples.

Json Tree
Jackson treats a json string as a tree with the entire tree and each node of that tree represented as an instance of com.fasterxm.jackson.databing.JsonNode class.

Thus,
1. Complete json is a JsonNode. Example,

[
  {
   "name":"Abc", 
   "age":12
  },
  {
   "name":"Def", 
   "age":15
  }
]

2. A single json element of a json string array is also a JsonNode. Example,

{"name": "Abc", "age":12}

3. Each node(or key-value) pair is also a JsonNode. Example, name=Abc
Refer below image to understand the concept of JsonNode
json node jackson objectmapper
So, a json tree is a collection of JsonNode instances.

To read json into a JsonNode, use readTree() method Jackson ObjectMapper class supplying it the json string argument as shown below.

String json = "{\"brand\":\"Abc\", \"model\":\"XYZ\"}"; 
try {
  JsonNode jsonNode= mapper.readTree(json);
} catch (JsonMappingException e1) {
  e1.printStackTrace();
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Node returned with readTree() is often referred to as the root node.
Get node with name
Once json tree is parsed into a JsonNode, we can get a node using its name or key using get() method which takes the name or key of node as argument. Example,

String json = "{\"brand\":\"Abc\", \"model\":\"XYZ\",\"ram\":null}"; 
try {
  JsonNode root = mapper.readTree(json);
  // get node
  JsonNode jsonNode = root.get("brand");
  // get node value
  System.out.println(jsonNode.asText()); // Abc
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Note that get() returns a JsonNode instance which represents a single key-value pair.

To get the value of this node as string, use its asText() method.

If the value of a node is of any other data type such as an integer, double, boolean etc., then directly use asInt(), asDouble(), asLong(), asBoolean() methods of JsonNode, instead of getting it as a string and then casting explicitly. Example,

String json = "{\"name\":\"Abc\", \"age\":2,\"weight\":11.5}"; 
try { 
  JsonNode root = mapper.readTree(json); 
  // get node 
  JsonNode jsonNode = root.get("name"); 
  // get string value 
  System.out.println(jsonNode.asText()); // Abc 
  jsonNode = root.get("age"); 
  // get int value 
  System.out.println(jsonNode.asInt()); // 2 

  jsonNode = root.get("weight"); 
  // get double value 
  System.out.println(jsonNode.asDouble()); // 12.5 
} catch (JsonProcessingException e1) { 
  e1.printStackTrace(); 
}

JsonNode also provides a path() method to get a node using its name.
It works the same as get() except that path() returns a MissingNode object if it cannot find a node with the given name, while get() returns null.
MissingNode is a special node for which all value accessor methods return empty value. path() is a convenient method if you want to avoid null checks on return values of get().

JsonNode default value
If the value for a key is set to null in json string, then it is possible to set some default value. All as- methods have an overloaded version that accept a value of the same data type.

If the value for a key is null, then this default value is returned. Example,

String json = "{\"name\":null, \"age\":2,\"weight\":11.5}"; 
try { 
  JsonNode root = mapper.readTree(json); 
  // get node JsonNode 
  jsonNode = root.get("name"); 
  // get string value 
  System.out.println(jsonNode.asText("NA")); // NA
} catch (JsonProcessingException e1) { 
  e1.printStackTrace(); 
}

Note that this will be useful when the value for a node is null.
If the node with a key is not present in json string, then get() will return null and calling asText() on null will raise a NullPointerException.
Find nodes with path
A json tree is similar to an XML document. So, the nodes are arranged in a hierarchy.
This means that nodes can be located according to their path starting from root using at() method which accepts the path of a node and returns it as JsonNode.
Example,

String json = "{\"name\":\"Abc\", \"age\":12," +
     \"address\":{\"pin\":12345}}"; 
try {
  JsonNode jsonNode = mapper.readTree(json);
  JsonNode path=jsonNode.at("/address/pin");
  System.out.println(path.asText());
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Note that the json string contains a nested node “pin” whose parent is “address” located at the top.
So, the path of “pin” will be “/address/pin”
If there is no node present at the given path, at() will return a MissingNode instance instead of null.
Getting field names
JsonNode has fieldNames() method which can be used to get all the fields names in json.
fieldNames() returns a java iterator and so we can loop through it. Example,

String json = "{\"name\":\"Abc\", \"age\":12,\"weight\":11.5}"; 
try {
  JsonNode jsonNode = mapper.readTree(json);
  Iterator<String> fields = jsonNode.fieldNames();
  while(fields.hasNext()) {
    String field = fields.next();
    System.out.println("Field name: " + field);
  }
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Output is

Field name: name
Field name: age
Field name: weight

Getting nodes
JsonNode has fields() method which can be used to get all nodes on json in key-value pairs.
fields() returns an iterator and so we can loop through it. Example,

String json = "{\"name\":\"Abc\", \"age\":12,\"weight\":11.5}"; 
try {
  jsonNode = mapper.readTree(json);
  Iterator<Entry<String, JsonNode>> fields = jsonNode.fields();
  while(fields.hasNext()) {
    Entry<String, JsonNode> node = fields.next();
    String fieldName = node.getKey();
    JsonNode valueNode = node.getValue();
    System.out.println("Key:"+fieldName +
            ", Value: " + valueNode.asText());
  }
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Note that key is a string since node name will always be a string while value is a JsonNode, since it can be a plain node or a nested node or an array.
Output is

Key: name, Value: Abc
Key: age, Value: 12
Key: weight, Value: 11.5

JsonNode with json array
If json string is an array, then each array element is also a JsonNode as shown below.
To fetch a node with name, first we need to get the array element in which the required node lies using the index of array node.
json arrayJsonNode provides an overloaded get() method which takes an integer argument. This integer represents the index of json element in array. Example,

String json = "[{\"name\":\"Abc\", \"age\":12}]"; 
try {
  JsonNode root = mapper.readTree(json);
  // get array node
  JsonNode arrayNode = root.get(0);
  // get node with name
  JsonNode jsonNode = arrayNode.get("name"); // Abc
  System.out.println(jsonNode.asText());
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

Thus, with json arrays, we need to first get the array node and then reach towards the desired node.
Iterating over array
Below is an example of iterating over a json string containing array.
Logic remains the same as with the plain json except that first we need to get the array node and then iterate over individual nodes inside this array.

String json = "[{\"name\":\"Abc\", \"age\":12}," +
               {\"name\":\"Def\", \"age\":2}]";
try {
  JsonNode root = mapper.readTree(json);
  int size = root.size();
  for (int i = 0; i < size; i++) {
    JsonNode arrayNode = jsonNode.get(i);
    System.out.println("Iterating over array element: "+(i+1));
    Iterator<Entry<String, JsonNode>> fields = arrayNode.fields();
    while (fields.hasNext()) {
      Entry<String, JsonNode> node = fields.next();
      String fieldName = node.getKey();
      JsonNode valueNode = node.getValue();
      System.out.println("Key:" + fieldName + 
             ", Value: " + valueNode.asText());
    }
  }
} catch (JsonProcessingException e1) {
  e1.printStackTrace();
}

That is all on using JsonNode to get nodes of a json, get their values, iterate over json string and json array.