JsonCpp

Foreword
This book describes the JsonCpp library (also called jsoncpp and json-cpp), JsonCpp is probably the most popular library for working with JSON databases in C++. It can parse and save databases, and provides an extensive library for accessing and manipulating their members. JsonCpp works with both files and strings.

For a library which exists for years, JsonCpp is surprisingly poorly documented. You can find either a very simple example of usage, or a computer-generated list of all classes and methods.

I am not an author, nor a contributor, of the library.

JSON
JSON (JavaScript Object Notation) is an ASCII format for representing various data structures. It is pretty language-independent, machine-independent, simple, and easy readable by both humans and computers.

JSON is fully described at json.org.

In brief, a JSON value can be one of the following (see json.org for full details):

\" - quote   \\ - backslash    \/ - slash    \n - newline    \t - tabulation    \r - carriage return    \b - backspace    \f - form feed    \uxxxx, where x is a hexadecimal digit - any 2-byte symbol    [1, 2, 3, "Hello world\n", true]    key : value where key is a string, value is any JSON value. Example:    {"foo":1, "bar":2, "baz":3.14, "hello world":[1,2,3]}
 * null
 * true or false
 * A number.
 * Numbers cannot start with 0 (or -0) followed by another digit (e. g. 0 and 0.14 are valid numbers, while 03, 012.34, and -015 are not).
 * If a number contains a decimal point, it should also contain at least one digit both before and after the decimal point (e. g. numbers 15. and .15 are invalid).
 * A string. Strings are enclosed in double quotes and may contain the following escape sequences:
 * An array. It is denoted by a comma-separated list of any values in square brackets. Example:
 * An object, also called associative array, keyed list etc. It is denoted by comma-separated list of pairs in braces. A pair has a form

Whitespaces can be inserted between any tokens.

Array elements are accessed by their number, while object elements are accessed by key. Arrays and objects can be empty. Arrays and objects can recursively contain another arrays or objects.

While strict JSON syntax does not allow any comments, and requires the root value to be array or object, JsonCpp allows both C-style and C++-style comments, and allows the root value to be of any type.

As for February 2016, there are totally hundreds of libraries for parsing and generating JSON on 62 languages, including 22 different libraries for C++.

JsonCpp is probably the most popular C++ library. Another popular library is rapidjson, which is very fast.

With apt or apt-get
The easiest way to use it from Ubuntu or another flavor of Debian Linux, is to install is as: sudo apt-get install libjsoncpp-dev (You may use  instead of  .)

One drawback is that it will not install the last version. For Ubuntu 18.04.1, the version is 1.7.4, while the last version as per August 2018 is 1.8.4. The problem was much worse for 14.04, which installed 0.6.0, while the last version as per February 2016 was 1.7.4.

To use JsonCpp, include: #include 

To compile a file, add flag -ljsoncpp

The header files will be installed to /usr/include/jsoncpp/json. In case you are curious, the libraries will be most probably installed to /usr/lib/x86_64-linux-gnu (but you hardly need their location). If you want to discover, try: ls /usr/lib/*/*jsoncpp* ls /usr/lib/*jsoncpp*

With amalgamated source
To use JsonCpp with amalgamated source, you don't need to download or make any binary files. You will have a single cpp and two .h files which you should include into your projects. These files will be system-independent.


 * Download and unzip the source from the official repository. Go to the directory.

python amalgamate.py
 * Run

It will create three files dist/jsoncpp.cpp, the source file to be added to your project dist/json/json.h, the correspondent header file dist/json/json-forwards.h, which contains forward declarations of JSON types.

You don't need anything except these three files.

With cmake
sudo apt-get install cmake mkdir -p build cd build cmake -DCMAKE_BUILD_TYPE=release -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" .. make (You may use  flag to parallelize the building, e.g.  .)
 * Download and unzip the source from the official repository. Go to the directory.
 * Install cmake. Under Ubuntu or another flavour of Debian Linux:
 * Create the build directory and enter it:
 * Run the cmake command
 * Run the make command:

Under Unix, it will create the file src/lib_json/libjsoncpp.a in your build directory. The include files will be in the ../include/json. Install the files ( might help), and use #include  and -ljsoncpp

With MS Visual Studio

 * Download and unzip the source from the official repository.
 * In this unzipped source tree, under makefiles/msvc2010 (for MS Visual Studio 2010) or vs71 (MS Visual Studio 2003) you will find several Visual Studio project files which you can up convert and build.

Example
Install JsonCpp.

Create file alice.json with the following contents:

Create file alice.cpp with following contents:

Compile it: g++ -o alice alice.cpp -ljsoncpp

Then run it: ./alice

You will hopefully receive the following:

Conventions and restrictions of JsonCpp
Everything is in the Json namespace.

Names of classes and other types use upper CamelCase notation (capitalize first letter of each word). Examples:,  ,. Names of member functions, fields, enum values use lower camelCase notation (capitalize first letter of each word except the first word). Examples:,  ,.

JsonCpp performs extensive validity checking. If an operation is invalid, it throws the  exception with relevant message.

JsonCpp stores each number as either 64-bit integer ( or  ), or 64-bit unsigned integer (  or  ), or. Below, we are going to call these int, uint, and real respectively.

An array or an object may contain at most $$2^{32}-1$$ elements. A string may contain at most $$2^{32}-1$$ characters. An object key may contain at most $$2^{30}-1$$ characters.

Auxiliary types
JsonCpp provides several auxiliary types.

The following types are defined in  :
 * Int - defined as
 * UInt - defined as
 * Int64 - a 64-bit signed integer, defined as  for Microsoft Visual Studio, otherwise
 * UInt64 - a 64-bit unsigned integer, defined as  for Microsoft Visual Studio, otherwise
 * LargestInt - a largest possible signed integer, defined as
 * LargestUInt - a largest possible unsigned integer, defined as

ArrayIndex is a type for array indices. It is defined as, which means that an array or object may contain at most $$2^{32}-1$$ items.

ValueType is an enum describing a type of JSON value. It is defined as:

Input/output
The simplest way to do input/output is via  and. The program below reads a JSON value from standard input and writes it to standard output. In case of syntax error,  throws   exception.

For example:

For reading this way from a string, or writing to a string, you may use  and   respectively, but there are alternative ways to do it.

toStyledString
The method toStyledString converts any value to a formatted string. Its declaration is:

Json::Reader
Another, and more robust, way to read JSON values is via the Reader class. Its most useful public methods are (here and below, comments are mine, and the order of methods is also mine):

Example:

Json::Writer
Unlike, the class Writer is abstract. There are two classes which implement it:
 * FastWriter produces unformatted, non-human-readable documents. Everything will be written in a single line.
 * StyledWriter produces formatted, human-readable documents, similar to, but with less indentation and without empty lines.

has the following public methods (default constructor and destructor are not shown):

has the following public method (default constructor and destructor are not shown):

StyledStreamWriter
Finally, there is also StyledStreamWriter class, for writing to streams. It is directly called by. This class is not a descendant of  or any other class. Its public methods are: is not very useful, as  is more convenient. You may want to use it if you want non-standard indentation.

Example:

Examining the attributes
The following method of Value returns some info about it:

,,  ,  ) return   only if all the following conditions satisfied:
 * the type is numeric (int, uint, or real)
 * if the type is real, the value should have zero fractional part
 * the value should be within the range of the given type (, ,  ,   respectively)

and  currently return   if the type is int, uint, or real.

always returns  for an int or uint. For a real value, it returns  if the value has zero fractional part, and within the range of   or. For all other types, it returns.

is... functions are not backwards-compatible. In versions 0.*,  and   just checked the type,   and   did not exist,   and   also returned true for null value,   also returned true for booleans etc.

Example:

Getting the value
To get the numerical, boolean, or string value itself, the class Value provides following methods:

Some of these methods may throw. A simple rule: if  returns true, then it is safe to call , but the opposite is not necessarily true.

Another rule, it is always safe to call
 * for string
 * for int
 * for uint
 * or  for any number (int, uint, or real)
 * for boolean

Below are the details.

The methods,  ,  ,  ),  ,   do the following:
 * If the original value is numeric, check if it is within the range of the destination type. If not, throw . Then cast the value to the destination type. The casting is plain, so the real value of 3.9, when sent to , becomes 3.
 * If the original value is boolean or null, return 1 for true, 0 for false, and 0 for null.
 * For strings, arrays, and objects, throw.

The methods  and   do the following:
 * If the original value is numeric, cast it to  or.
 * If the original value is boolean or null, return 1.0 for true, 0.0 for false, and 0.0 for null.
 * For strings, arrays, and objects, throw.

The method  accepts anything.
 * false, null, 0, 0.0, or empty string/array/object is converted to
 * true, non-zero number, or non-empty string/array/object is converted to

The method  is robust, slow, and high level. It returns. It correctly treats strings with zero characters. It accepts everything except arrays and objects. For a null, the method returns ; for a boolean, it returns   or  ; for a number, it returns it's string representation. For arrays and objects, it throws  exception.

The method  is the fast, low-level method. It accepts only strings (otherwise it throws  exception), and directly returns the C-style string which is stored internally. The method doesn't allocate anything. Don't call  or   on the returned pointer! You should keep in mind two things:
 * Since C-style strings should not contain zero characters, the method is only suitable for strings without zero characters.
 * For empty strings, it sometimes returns 0.

If you need a C-style string, but don't want to be confused by zero characters, newer versions of JsonCpp add the following method:

This method stores the pointer to the first character to, stores the pointer to the final zero character to  , and returns. For non-strings and sometimes for empty strings, it returns.

Example :

Constructors, assignment and comparison
The class Json::Value provides following constructors:

The first constructor creates null, false, 0, 0.0, or empty string/array/object. The other constructors are self-explanatory.

Assignment, swap, and all comparison operators are also provided (as methods).

Methods for arrays
Arrays have their own methods. These methods also work for null.

Some of them are similar to C++ STL's vectors: Note that ArrayIndex is defined as unsigned int.

changes the array size by either removing last values or appending null values.

If  receives a negative index, it throws the   exception. If it receives  which is equal to or greater than the current size,
 * non-constant  appends   null values, then returns the last value
 * constant  returns the null value

To append a value, use append: This is similar to C++ method. In other words,  is equivalent to.

The method get returns -th element, or   if   is greater or equal to size: Note that it returns value NOT by reference, so calling this method may be very expensive.

To check validity of an index, you may want to use isValidIndex: This is not very useful, as  is equivalent to.

You can also remove one value with removeIndex: No miracles, this method takes linear time. If  is greater or equal to size, it returns.

Calling array methods for null value
If  is null, the methods above treat it as an empty array:
 * returns
 * returns 0
 * does nothing
 * does nothing
 * for positive size transforms  into an array of   nulls.
 * (non-constant) transforms  into an array of   nulls, then returns the last value
 * (constant) returns the null value
 * always returns
 * always returns
 * makes  an array of one element, which equals to
 * always returns false

Calling array methods for other types
The methods,   and   also work for objects.

Other than this, calling any of the methods above for something which is neither array nor null is pretty useless. They either return something trivial or throw the  exception:
 * returns, unless   is an empty object
 * returns 0, unless  is an object
 * throws the  exception, unless   is an object
 * ,,  ,   throw the   exception
 * always returns
 * always returns

Methods for objects
Objects have their own methods. These methods also work for null.

Some of them are similar to C++ STL's maps: These are self-explanatory. For, if the key does not exist, non-constant   inserts the (key, null) pair and returns the reference to this null, while constant   just returns the reference to some null.

The following methods take a key as either C++ string, C string, or a pair of pointers specifying beginning and end of the string. The last form does not exist in old versions of JsonCpp. It is useful, for example, if a string contains zero characters.

The method isMember checks whether there exists a member with given key:

The method removeMember removes an element. The first two forms return the removed value NOT by reference, which may be pretty expensive.

To iterate through the members of an object, you need the full list of their keys. This is performed by getMemberNames: Value::Members is defined as:

The method get returns value for the given key, or, in its absence,. Just like with arrays, it returns value NOT by reference, so calling this method may be very expensive.

The method find exists only in newer versions. It receives the key in (begin, end) form and returns pointer to the found value. If not found, it returns  pointer.

Calling object methods for null value
The methods above treat null value as an empty object:
 * does nothing
 * returns 0
 * returns true
 * non-constant  transforms the value into one-element object, with given key and null value
 * constant  returns null
 * returns null (deprecated variants) or  (new variants).
 * returns empty vector of strings
 * returns
 * returns

Calling object methods for other types
The methods,  ,   work also for arrays. Other than this, for a value which is neither null nor an object, the methods above return trivial value or throw the  exception.

Examples of work with objects and arrays
Creating a complex structure:

Recursive function for printing any value (of course, it already exists, but we implement it from scratch):

Iterators
Iterators have types Json::Value::iterator and Json::Value::const_iterator. They are bidirectional, but not random. The methods of Json::Value are

Only arrays and objects have non-trivial iterators. If  is neither array nor object, then   equals to.

Iterators have the full set of operators: incrementing and decrementing (postfix and prefix  and  ), comparison to equality and inequality, assignment, default constructor and copy constructor. Iterators are not random, so adding an integer number to iterator is not possible. Subtracting iterator from another iterator is possible, but takes linear time.

If  is an iterator to an array, then   is a reference to the respective array's element. If  is an iterator to an object, then   is NOT a reference to the (key, value) pair. It is a reference to the value itself.

is available since versions 1.*.

Example: will print:

To receive key (for iterator to object) or index (for iterator to array),  and   provide three methods:

As explained in comments,  returns the key for an object element or the index for an array element;   returns the index for an array element, otherwise  ;   returns the key for an object element, otherwise empty string.

Example:

This works for newer version only. This prints:

For an older version, we cannot initialize Json::Value::const_iterator as Json::Value::iterator, and there is no operator->.

Iterators in old versions
In versions 0.*, casting from  to iterator is not possible, while the corresponding assignment is possible. For example, if  is not constant, we cannot write Instead, we should use. Besides, there is no.

Therefore, instead of the program above, we should write: