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.