This tutorial will teach you how to navigate or modify a JSON Document using a JSON Pointer, which is available in javax.json API.
Put it simply, a JSON Pointer is a string that references an element within a JSON document. By using a JSON pointer, an application can retrieve a value, but it can modify as well a JSON document.
To create a pointer, you call the static method Json.createPointer and pass the pointer expression as an argument. The factory method returns an instance of JsonPointer.
Let’s assume you have the following JSON Document:
{
"Actors": [
{
"name": "Tom Cruise",
"age": 56,
"Born At": "Syracuse, NY",
"wife": null,
"weight": 67.5,
"hasChildren": true,
"hasGreyHair": false,
"children": [
"Suri",
"Isabella Jane",
"Connor"
]
},
{
"name": "Robert Downey Jr.",
"age": 53,
"Born At": "New York City, NY",
"wife": "Susan Downey",
"weight": 77.1,
"hasChildren": true,
"hasGreyHair": false,
"children": [
"Indio Falconer",
"Avri Roel",
"Exton Elias"
]
}
]
}
The following snipped from a Servlet will capture the index “0” of the “Actors”Path:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
try {
PrintWriter writer = resp.getWriter();
JsonReader jr = Json.createReader(this.getClass().getClassLoader().getResourceAsStream("data.json"));
JsonStructure js = jr.read();
JsonPointer jp = Json.createPointer("/Actors/0");
JsonObject jsonObject = (JsonObject) jp.getValue(js);
writer.println(jsonObject.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
As you can see, every pointer expression starts with “/” which means the root object. The special “/n” syntax can be used to access the nth element of an array.
The above example will obviously print:
{
"Actors": [
{
"name": "Tom Cruise",
"age": 56,
"Born At": "Syracuse, NY",
"wife": null,
"weight": 67.5,
"hasChildren": true,
"hasGreyHair": false,
"children": [
"Suri",
"Isabella Jane",
"Connor"
]
}
]
You can use the containsValue to verify if a JsonPointer points to a key that exists in the JSON document. For example, if the Actor n. 0 has the “children” key in it:
JsonPointer jpChildren = Json.createPointer("/Actors/0/children");
boolean hasChildren = jpChildren.containsValue(js);
if (hasChildren) {
// iterate over the array
JsonArray all = (JsonArray) jpChildren.getValue(js);
writer.println(all.size());
for (int ii=0;ii<all.size();ii++)
writer.println(all.get(ii));
}
As we said, you can use a JsonPointer also to add a new value. For example, we will add a new property named “BirthDate” to our Actor n.0 :
JsonPointer jpBirthDate = Json.createPointer("/Actors/0/BirthDate");
JsonString jsBirthDate = Json.createValue("July 3, 1962");
js = jpBirthDate.add(js, jsBirthDate);
When adding elements to an array there’s a caveat though. If just add an element to an array using the above JsonPointer expression that will replace all existing array elements. The solution is to use the special “-” character at the end of the Pointer expression, which will preserve the existing Array elements. For example:
JsonPointer jpChild = Json.createPointer("/Actors/1/children/-");
JsonString jsChild = Json.createValue("New Baby");
js = jpChild.add(js, jsChild);
Then, to replace a value, you can use the replace method to change an element’s value:
JsonPointer activePointer = Json.createPointer("/Actors/0/BirthDate");
modifiedJsonObject = activePointer.replace(jsonObject, "July 3, 1972");
Finally, you can use the remove method to delete a key element from a JSON:
JsonPointer activePointer = Json.createPointer("/Actors/0/BirthDate");
modifiedJsonObject = passwordPointer.remove(jsonObject);
You can find this source code in my Github repository https://github.com/fmarchioni/mastertheboss/tree/master/json which is ready to run on WildFly.