Skip navigation links
Introduction

See: Description

Packages 
Package Description
com.ak.json  
com.ak.json.nodetree  
com.ak.json.transform  

Introduction

Jsonnodetree is library that is parsing JSON textual document to tree of a nodes, each of them represents JSON entity: object, array or value of primitive type. Generated tree allows to modify values of nodes and/or structure of the given JSON document. The library is extended with set of operations with paths and transformations similar XPATH and XSLT for XML.

Getting started

Assume we have a JSON document in file phones.json:


 {
   "name": "John",
   "age": 25,
   "address": {
     "street": "15, Main St.",
     "city": "Bloomington",
     "state": "Texas"
   },
   "phones": [
     4143456798,
     7189151248,
     {
       "type": "office",
       "number": 7189257336
     }
   ]
 }
  
To parse this document to node tree we have to write code:

 JNode docTree = new com.ak.json.transform.JParser().parse(new File("phones.json"));
  

The JSON parser converts textual presentation of the document to a tree of nodes:

Result of parsing is a tree of nodes as a next figure showed:

Node type JNodeObject represents JSON object (f.e. {"street": "15, Main St.", "city": "Bloomington", "state": "Texas"}).
JNodeArray nodes represent JSON arrays (f.e. [4143456798, 7189151248, "comcast"]).
JNodeValue nodes represent JSON primitive values like string, integer number, float number, boolean and null.

Class diagram of the library is showed below. Interface Node represents all common operation under nodes tree.

Find and Get nodes


 docTree.get("age").getValue(Integer.class));                  // == 25
 docTree.get("phones").get(0).getValue(Long.class));           // == 4143456798l
 docTree.get("address");                                       // == JObjectNode represents "{"street":"15, Main St.","city": "Bloomington","state": "Texas"}") 
 docTree.get("address").get("street");                         // == JValueNode<String> represents "15, Main St.", 
 docTree.get("address").get("street").getValue(String.class)); // == "15, Main St."
  

Change value


 JValueNode<Object> changedNode = (JValueNode<Object>) docTree.get("age"); // changedNode represents 25
 changedNode.setValue(new Integer(27));                                    // now changedNode represents 27
  

Add nodes


 JArrayNode changedNode = (JArrayNode) docTree.get("phones"); // changedNode represents [4143456798,7189151248,{"type":"office","number": 7189257336}]
 changedNode.addElement(new JValueNode(4043242668L));         // now changedNode represents [4143456798,7189151248,{"type":"office","number": 7189257336},4043242668]
  

 JObjectNode changedNode = (JObjectNode) docTree.get("address"); // changedNode represents {"street":"15, Main St.","city":"Bloomington","state":"Texas"}
 changedNode.addElement("zip code", new JValueNode(33024));      // now changedNode represents {"street":"15, Main St.","city":"Bloomington","state":"Texas"."zip code":"33024"}
  

Remove nodes


 ((JObjectNode) docTree).removeElement("name");
 docTree.get("name")); // == null
  

JPath

JPath has a purposes, notation and functionality similar XPATH. With JPath we can issue requests to search and extract nodes from node tree:


 List result = JPath.jpath("/address/street", docTree); // == [JValueNode -> "15, Main St."] 
  
To show all power of JPath we need more composite JSON document for examples. Imagine it keeps in book_store.json file:

{"book-store": [
  {"book": {"title": "The Great Gatsby",
            "author": {"first-name": "Francis Scott", "last-name": "Fitzgerald"},
            "price": 8.41, "year": 2004}},
  {"book": {"title": "Joyland (Hard Case Crime)",
            "author": {"first-name": "Stephen", "last-name": "King"},
            "price": 7.77, "year": 2013}},
  {"book": {"title": "Doctor Sleep: A Novel",
            "author": {"first-name": "Stephen", "last-name": "King"},
            "price": 17.45, "year": 2013}},
  {"book": {"title": "Adventures of Huckleberry Finn", 
            "author": {"first-name": "Mark", "last-name": "Twain"},
            "price": 2.70, "year": 1994}},
  {"book": {"title": "The Call of the Wild",
            "author": {"first-name": "Jack", "last-name": "London"},
            "price": 8.15, "year": 2013}},
  {"book": {"title": "Martin Eden", 
            "author": {"first-name": "Jack", "last-name": "London"},
            "price": 10.09, "year": 1909}},
  {"book": {"title": "Roadwork",
            "author": {"first-name": "Stephen", "last-name": "King"},
            "price": 7.19, "year": 2013}}
]}
  
First at all convert Json document to node tree:

 JNode bookStore = parser.parse(new File("book_store.json"));    
    
Now try to extract from book store all book titles (nodes named "title"):

 List result = JPath.jpath("/book-store/*/book/title", bookStore); 
    
If we print out result

 for (JNode nd : result) {
   System.out.println(nd.toJson());
 }
  
we get result in as a text values of json fields "title" like this:

 "The Great Gatsby"
 "Joyland (Hard Case Crime)"
 "Doctor Sleep: A Novel"
 "Adventures of Huckleberry Finn"
 "The Call of the Wild"
 "Martin Eden"
 "Roadwork"
  
Json path expression mostly looks like XPath expressions. A location json path expression consists of one or more steps, each separated by a slash.

 /step1/step2/ ...
    
The path can be absolute (starting with /) or relative (without leading /). Each step is evaluated against the nodes in the current node-set. A step consists of: The syntax for a location step is:

 axisname::nodetest[predicate]
    

JPath axes: an axis defines a node-set relative to the current node.
Axis NameResult
ancestorSelects all ancestors (parent, grandparent, etc.) of the current node
ancestor-or-selfSelects all ancestors (parent, grandparent, etc.) of the current node and the current node itself
childSelects all children of the current node
descendantSelects all descendants (children, grandchildren, etc.) of the current node
descendant-or-selfSelects all descendants (children, grandchildren, etc.) of the current node and the current node itself
following-siblingSelects all siblings after the current node
parentSelects the parent of the current node
preceding-siblingSelects all siblings before the current node
selfSelects the current node

Examples of axis

If we run code


 List result = JPath.jpath("/book-store/4/book/child::.", bookStore); 
    
JPath will select 4th object from "book-store" array. It will be object:

 {"book": {"title": "Adventures of Huckleberry Finn", 
           "author": {"first-name": "Mark", "last-name": "Twain"},
           "price": 2.70, 
           "year": 1994
          }
 }
 
Then JPath selects "book" object that is

 {"title": "Adventures of Huckleberry Finn", 
  "author": {"first-name": "Mark", "last-name": "Twain"},
  "price": 2.70,
  "year": 1994
 }
 
And last step "child::." causes selecting all children from current node:

"The Call of the Wild"
{"first-name":"Jack","last-name":"London"}
8.15
2013
 

Node test
ExpressionDescription
nodenameSelects all nodes with the name "nodename"
/Selects from the root node
//Selects nodes in the document from the current node that match the selection no matter where they are
.Selects the current node
..Selects the parent of the current node
*Selects any nodes
integer numberSelects node from array by the index

Predicate examples

Predicate exists in two forms. First form compares values of nodes:

 
 [NodeValue1 ValueCondition NodeValue2]
   - where
   ValueCondition : eq, ne, lt, le, gt, ge
 
Other form compares a set of Nodes:
 
 [NodeSet1 NodeSetCondition NodeSet2]
   - where
   NodeSetCondition : =, !=, <, <=, >, >=
 
Comparison of node sets returns true if it is possible to find pair of nodes from first and second set that their values will satisfy corresponded condition. For example set of nodes: ("a", "b") will be equals {=} ("a", "c"). There is example of using predicate in JPath:

 List result = JPath.jpath(""/book-store/*/book[author/last-name eq \"King\"]/title", bookStore); 
    
We will select titles of all books of author "King":
 
 Joyland (Hard Case Crime)
 Doctor Sleep: A Novel
 Roadwork
  

Json transformation

Json Node Tree framework allows transformation of JSON object like XSL transformation XML documents. Suppose we have initial document:


{"book-store" : [
  {
    "book" : {
      "title": "The Great Gatsby",
      "author" : {
        "first-name" : "Francis Scott",
        "last-name" : "Fitzgerald"
      },
      "price" : 8.41,
      "year" : 2004
    }
  },
  {
    "book" : {
      "title" : "Joyland (Hard Case Crime)",
      "author" : {
        "first-name" : "Stephen",
        "last-name" : "King"
      },
      "price" : 7.77,
      "year" : 2013
    }
  }]
}
    
Json document named 'template' defines transformation we want to apply to original document:

[
  {
    "$template" : {
      "$match" : "/", 
      "$value" : {
        "authors" : {"$apply-template" : {"$select" : "/book-store/*[not(book/author/last-name = preceding-sibling::book/author/last-name)]/book/author"}}
      }
    }
  },
  {
    "$template" : {
      "$match" : "book", 
      "$value" : {
        "book" : {
          "title" : {"$value-of" : {"$select" : "title"}}
        }
      }
    }
  },
  {
    "$template" : {
      "$match" : "author",
      "$variable" : {"$name" : "author", "$select" : "."}, 
      "$value" : {
        "author" : {
          "name" : {"$value-of" : [{"$select" : "first-name"}, " ", {"$select" : "last-name"}]
          },
          "books" : {"$apply-template" : {"$select" : "/book-store/*/book[author = $author]"}}
        }
      }
    }
  }
]
    
Result the transformation is following:

{
  "authors":[
    {
      "author":{
        "name":"Francis Scott Fitzgerald",
        "books":[
          {
            "book":{
              "title":"The Great Gatsby"
            }
          }
        ]
      }
    },
    {
      "author":{
        "name":"Stephen King",
        "books":[
          {
            "book":{
              "title":"Joyland (Hard Case Crime)"
            }
          }
        ]
      }
    }
  ]
}
    

Json templates document is analog of XML stylesheet document (usually .xsl file) <xsl:stylesheet></xsl:stylesheet>. It is Json array of template objects:

{
  "$template": {
    "$match": {},
    "$value": {}.
    "$variable": {}
  }
} 

Transformation template tags
Template tag (Json)XSLT analogDescription
$template <xsl:template> ""
$apply-template <xsl:apply-templates> ""
$match <xsl:template match=pattern> ""
$select <xsl:apply-templates select=expression> ""
$value-of <xsl:value-of select=expression> ""
$value ""
$variable <xsl:variable> ""
$name ""
$_variable_name_ "_variable_name_" "_variable_name_"

Skip navigation links