JSON Parser
JSON (JavaScript Object Notation) is a lightweight data-interchange format. Basically a JSON object is a comma separated list of pairs, enclosed in curly braces. A pair consists out of a label and a value, separated by a colon. E. g.:
{
"name" : "Mike",
"age" : 23,
"hobbies" : [ "fishing", "rugby", "computer
games" ]
}
The value can hold different kind of data, e. g. strings, numbers or even arrays. This seems very easy but can become rather complicated if a value is another JSON object: We have a recursive structure then, and a JSON object is best represented by a tree of nodes therefore. All strings (and the labels) must be enclosed in quotes, all other types must not. See www.json.org for details.
Features
The JSON parser comes as the Java library JsonFse in a JAR file. It is a simple implementation which accepts only Java Strings as input. I have needed the parser for my Camera RC project, and I did not like to familiarize myself with other JSON libraries. And to write a recursive parser after some years again promised fun!- The parser analyses the input string, i. e. build the parse tree and put each recognized leaf into the tree.
- The parser detects syntactical errors in the string and shows the position of the error.
- You can traverse through the tree and get single elements of it.
- You can build or modify a tree by adding single elements.
- There is a full documentation in Java Doc format.
- The library is open source (LGPL).
Examples
To parse a JSON string and build the tree it must be given as a Java String to the constructor of the JsonFse.JsonObj class. Example:
import JsonFse.*;
String s = "{" +
"\"name\" : \"Mike\"," +
"\"age\" : 23," +
"\"hobbies\" : [ \"fishing\", \"rugby\", \"computer games\" ]" +
"}";
try
{
JsonObj jo = new JsonObj(s);
System.out.println(jo.getAsString());
}
catch (ParseErrorEx ex)
{
System.out.println(ex.getErrMsg());
}
JsonObj.getAsString() retranslates the tree recursively into a formatted string. If the original string could not be parsed because of an error a ParseErrorEx exception is thrown. ParseErrorEx.getErrPos() delivers the index in the string where the error is detected, ParseErrorEx.getErrMsg() gets a complete error message.
To traverse through the JsonObj tree some knowledge of
the node types is necessary. Their names reflect the names given in
www.json.org. The abstract base
class is Node, NodePair represents a
pair, NodeNumber
a number etc. To get pairs in a
JSON object there are the methods JsonObj.getNext()
and JsonObj.get(). The same methods are available in
the NodeArray class. Example traversing through the
JSON object jo created above:
NodeString ns, nsa;
NodeValue nv;
NodePair np = jo.getNext();
while (np != null)
{
ns = np.getString();
System.out.println("label: " + ns.getAsString());
nv = np.getValue();
if (nv instanceof NodeArray)
{
nsa = (NodeString)nv.get(1);
System.out.println("Second hobby of Mike: " + nsa.getAsString());
}
np = jo.getNext();
}
System.out.println("First pair in jo: " + jo.get(0).getAsString());
This produces the output:
label: "name"
label: "age"
label: "hobbies"
Second hobby of Mike: "rugby"
First pair in jo: "name" : "Mike"
As you can see it is easy to get a special value in a JSON object or of an array in it if you know the structure of the JSON object. If you do not know the structure you need to recognize it while traversing through the structure. Use the Java command instanceof to detect the type of unknown values as shown above.
To see how to create a JSON object and for further details have a look at the library's documentation.
Grammar
The implementation is able to parse JSON objects according to this
grammar, notated in EBNF:
object = '{' , [ members ] , '}' ;
members = pair , { ',' , pair } ;
pair = string , ':' , value ;
string = '"' , { char } , '"' ;
char = ? any Unicode character ?
- ctrlChar - '\') | ctrlChar | hexNumber ;
ctrlChar = '\"' | '\\' | '\/' | '\b' | '\f' | '\n' | '\r' | '\t' ;
hexNumber = '\u' , hexDigit , hexDigit , hexDigit , hexDigit ;
hexDigit = digit09 | hexChar ;
digit09 = digit0 | digit19 ;
digit0 = '0' ;
digit19 = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
hexChar = 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f' ;
value = string | number |
object | array | 'true' | 'false' | 'null' ;
number = int | int frac | int exp | int , frac , exp ;
int = [ '-' ] , digit | digit19 , digits ;
frac = '.' , digits ;
exp = eE , digits
digits = digit09 , { digit09 } ;
eE = 'e' | 'E' [ '+' | '-' ] ;
array = '[' , [ elements ] , ']' ;
elements = value , { ',' , value } ;
Symbol | Meaning |
---|---|
= | definition |
, | concatenation |
; | termination |
| | alternation |
[ ... ] | option |
{ ... } | repetition |
' ... ' | terminal string |
? ... ? | special sequence |
- | exception |
Class Diagram
The UML class diagram looks like this:
Download
File | Size | Description | Version | Platform |
---|---|---|---|---|
JsonFse_110.zip | 591 kB | JSON parser library | 1.1.0 | JRE 1.8.0 or newer |
JsonFse_src_110.zip |
97 kB | JSON parser library source code (Netbeans project) | 1.1.0 | Netbeans IDE 9.0 |
Change Log
16 December 2018, V.1.1.0:- New constructor
JsonObj(NodeObj)
and new methodJsonObj.setNodeObj(NodeObj)
are available; an already parsed JSON object can be reused without parsing its string again. - New constructor
NodePair(
String, int)
and new methodJsonObj.addPair(String, int)
to handle integer values.
- First published release.
- New method getAsInt() added.
- JUnit tests added.
Links
- This is the JSON home page with links to many parser implementations.
- The official Java implementation comes from Oracle.
- And finally a comparison between four other popular Java implementations.