You have already chosen Jackson as your Java-JSON library (which I could say is a good choice) so problem at your hand is how to use Jackson to traverse and update the JSON in best way, but those who are even deciding on which Java-JSON library to use can read here which compares below mentioned 7 Java-JSON libraries. Below is conclusion excerpt from link:
As a conclusion, if you know that you are going to use only a small
amount of data in your application and you wish to store or read it to
and from JSON format, you should consider using Flexjson or Gson. If
you are going to use large amounts of data and wish to store or read
it to and from JSON format, you should consider using Jackson or
JSON-lib.
- Jackson
- Google-GSON
- JSON-lib
- Flexjson
- json-io
- genson
- JSONiJ
Jackson
Most important thing to understand is that Jackson offers three alternative methods for processing JSON (read more here), so appropriate approach should be chosen wisely considering the specific requirements.
Streaming API (aka "Incremental parsing/generation"): It reads and writes JSON content as discrete events. Best case use: Iterating over Event (or, token) stream. Analogous to: SAX and Stax
Tree Model: It provides a mutable in-memory tree representation of a JSON document. The tree model is similar to the XML DOM. Best case use: Binding Json data into Java Objects. Analogous to: JAXB
Data Binding: It converts JSON to and from POJOs based either on property accessor conventions or annotations. There are two variants: simple and full data binding. Best case use: Building a tree structure (from Json) and traversing it using suitable methods. Analogous to: DOM
- Simple data binding means converting to and from Java Maps, Lists, Strings, Numbers, Booleans and nulls
- Full data binding means converting to and from any Java bean type (as well as "simple" types mentioned above)
Typically using "Tree Model" approach is considered as best from "performance perspective" because it gives advantages of traversing a tree.
Other options has also its own advantages like Streaming API has less memory and CPU overhead while Data binding is convenient to use because it provides List
and Map
representation of JSON data. However, with so much processing power and memory, these days what really matters is performance.
If your JSON data is huge and then analyze that in a tree representation whether tree would have wider width or longer length. If it has wider width then definitely using "Tree Model" will have performance advantages associated with a tree processing (make sure you are mapping in chunks and not whole stuff in one shot). But if tree is lengthier, meaning doesn't have good width but is like a very long tail, then consider using "Streaming API" because in that case advantages of tree processing cannot be substantiated. If data is small then it hardly matters and you can use "Tree Model" as default.
Currently you are using "Data Binding" approach but recommendation is to use "Tree Model" because all you need is traversal and manipulation of JSON. Looking at information you have given, it doesn't look like you need to convert your JSON into Java objects so "data binding" approach looks like a bad idea.
Jackson Tree Model
Jackson's com.fasterxml.jackson.databind.JsonNode
forms the basis of Jackson's tree model. Think of Jackson's Tree model as a DOM of HTML document, the way DOM represents complete HTML document in a tree structure, Jackson's Tree model represent complete JSON string in a tree strcuture.
Below is the code which will help you use Jackson's Tree model and achieve what you are looking for:
import java.io.IOException;
import java.util.Iterator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class Test {
public static void main(String[] args) throws JsonProcessingException, IOException {
String jsonString = "{\"test1\": {\"get\": {\"tags\": [\"restcalls1\"]}}, \"test2\": {\"put\": {\"tags\": [\"restcalls2\"] }}}";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonString);
Iterator<JsonNode> iterator2 = rootNode.iterator();
while (iterator2.hasNext()) {
JsonNode node2 = iterator2.next().findParent("tags");
ObjectNode objectNode = (ObjectNode) node2;
objectNode.putArray("tags").add("my rest calls");
}
Iterator<JsonNode> iterator = rootNode.iterator();
while (iterator.hasNext()) {
JsonNode node2 = iterator.next();
System.out.println(node2);
}
}
}
Tree model advantages:
Read
here for more details
- If the structure of Json content is highly irregular, it may be difficult (or impossible) to find or create equivalent Java object structure. Tree model may be the only practical choice.
- For displaying any JSON content. Tree model is a natural choice for internal access and manipulation.
- Since we do not need specific Java objects to bind to, there may less code to write.
Further readings:
Based on OP's comment:
Below code shows how you can traverse and print whole JSON. In this way, you can traverse whole JSON and then access elements you are looking for. Key think to note is that you need to know the element name, even if you use Stream API approach then also you should know the element name to look for, see Stream API example here
In any case, you can always choose to traverse the whole JSON (as shown in example below) or do specific and direct manipulation (as shown in example above)
package com.him.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws JsonProcessingException, IOException {
jacksonTest();
}
private static void jacksonTest() throws JsonProcessingException, IOException {
String jsonString = "{\"test1\": {\"get\": {\"tags\": [\"restcalls1\"]}}, \"test2\": {\"put\": {\"tags\": [\"restcalls2\"] }}}";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonString);
ArrayList<JsonNode> nodeList = new ArrayList<JsonNode>();
nodeList.add(rootNode);
printCompleteJson(nodeList);
}
private static void printCompleteJson(ArrayList<JsonNode> rootNode) throws IOException {
for (int i = 0; i < rootNode.size(); i++) {
Iterator<JsonNode> iterator = rootNode.get(i).iterator();
JsonNode node = null;
ArrayList<JsonNode> nodeList = new ArrayList<JsonNode>();
boolean isEmpty = true;
while (iterator.hasNext()) {
isEmpty = false;
node = iterator.next();
nodeList.add(node);
System.out.println(node);
}
if(isEmpty){
return;
}
printCompleteJson(nodeList);
}
}
}