Json-11 is yet another C++ class implementing JSON data interchange format. It is designed with the (currenly) latest C++11 standard in mind. The code fits in a single file, reasonably fast, and the interface is made as simple as possible. Implements parsing, formatting, traversing and editing, schema validation.
#include "json11.h"
Then drop json11.cpp into your project to compile. Note that you need a compiler that supports C++11. I only tested it with GCC 4.8.1 on Linux. For GCC don't forget to add -std=c++11
to compiler flags.
Json jnull; // creates a null Json object.
Json jtrue = true, pi = 3.14, str = "Hello"; // scalar objects
Json arr { 1, 2, str }; // array object, using initializer list
arr << false; // do you prefer 'push_back' ?
To create key-value objects, start with a null object. Then use method set(key,value)
or operator[]
to populate it.
Json obj;
obj.set("one", 1).set("pi", pi);
obj["arr"] = arr; // nice, but cannot be chained
Json hello = arr[2];
arr[2] = "bye"; // will affect obj["arr"], but not hello
cout << obj << endl; // prints {"one":1,"pi":3.14,"arr":[1,2,"bye",false]}
cout << hello << endl; // still prints "hello"
To extract scalar value from a Json instance, assign it to a scalar variable of matching type or use a cast. For collections use operator[]
with either integer or string indexes.
string text = str; // text is Hello (without quotes)
double num_pi = pi;
int one = obj["one"];
string hello = obj["arr"][2];
To 'stringify' a Json instance, write it to a std::ostream. To get it as a std::string use method stringify()
or its alias format()
:
string jsontext = obj.format();
To parse a JSON text, read it from a std::istream. To parse it from std::string use static method parse()
:
Json obj2 = Json::parse(jsontext);
cout << (obj == obj2) << endl; // prints true; yes, Jsons are comparable
ifstream fs("big.json");
Json big(fs);
To determine the type and size of a Json instance use methods type()
and size()
. The first one returns one of enum Json::Type
values:
enum Json::Type { JSNULL, BOOL, NUMBER, STRING, ARRAY, OBJECT };
The second one returns either number of array elements or number of properties of an object. Property names are returned by keys()
as vector<string>
. These methods, together with operator[]
allow to fully traverse an object.
The Json class defines two exception classes, parse_error
and use_error
. The first one can be thrown only from Json(istream&)
. The second is thrown when the class methods are used inappropriately, for example when operator<<
is used for an object. It is also thrown when adding to a container would lead to circular dependency, like in this example:
Json js1, js2;
js1 << 1 << 2;
js2 << js1;
js1 << js2; // error
The Json class methods can also throw standard exceptions out_of_range (from operator[]) and bad_cast.
- Json()
- Default constructor creates a Json null instance.
- Json(const Json&)
- Copy contructor.
- Json(Json&&)
- Move contructor.
- Json(std::istream&, bool full = true)
- Reads and parses well-formed JSON UTF-8 text. By default tries to parse until end of file. If not full, leaves input stream where all brackets are closed, so there may be more text.
- Json(T x)
- Conversions from scalar type T, where T is one of bool, int, long, long long, float, double, long double, const char*, std::string. Internally all numbers are stored as long double.
- Json& operator = (const Json&)
- Copy initializer.
- Json& operator = (Json&&)
- Move initializer.
- Json(std::initializer_list)
- Creates an instance representing JSON array. Elements of the initializer_list must be either Json instances or convertible to Json.
- virtual ~Json()
- Destructor.
- Type type() const
- Returns JSON type of this instance, one of enum Json::Type
- operator T() const
- If this instance represents a scalar value, returns it. T is one of bool, int, long, long long, float, double, long double, std::string. Throws std::bad_cast if wrong type is requested.
- Json& operator << (const Json&)
- Appends an element to the array. To create a new array just append something to a null instance, or use the constructor with initializer list.
- Json::Property operator [] (int) const
- Retrieves array element by index, as in `int x = arr[0]`, or replaces it, as in `arr[0] = "zero"`
- void insert(int index, const Json& that)
- Inserts that into array before index, so it becomes the one at index. If index < 0, counts from the end.
- Json& replace(int index, const Json& that)
- Replaces array element at index by that. If index < 0, counts from the end.
- void erase(int index)
- Removes element at index from the array. If index < 0, counts from the end.
These methods throw use_error
if this Json instance is not an array.
- Json& set(std::string key, const Json& value)
- Adds property "key:value" to this object, or replaces the value if key is already there. To create a new object, start from a null Json instance.
- Json get(const std::string& key) const
- Returns value for the given key, or `Json::undefined` if this instance does not have such property.
- Json::Property operator [] (std::string&)
- Returns value for the given key, or `Json::undefined` if this instance does not have such property. When used on the left of assignment operator as in `obj["key"] = value`, adds a key with given value or replaces existing one.
- Json::Property operator [] (const char*)
- Same as the previous one.
- bool has(const std::string& key) const
- Returns `true` if this instance has propery with given key.
- std::vector keys()
- Returns all property keys for this instance.
These methods throw use_error
if this Json instance is not an key-value object.
Technically, operator[]
returns and instance of internal class Json::Property. Instances of this class behave very much like Jsons, so in practice you don't have to remember about it.
- bool operator == (const Json&)
- Compares Json instances. Scalars are equal if and only if they have same types and same values. Arrays are equal if their elements and order of them are the same. Objects are equal if their property keys and corresponding values are equal, regardless of order.
- bool operator != (const Json&)
- The opposite.
- static Json parse(const std::string&)
- Returns a Json instance built from well-formed JSON text. UTF-8 encoding is assumed. See also Json(std::istream&).
- std::string stringify()
- Returns well-formed JSON text representing this object as a string.
- std::string format()
- Same as stringify().
- friend std::ostream& operator << (std::ostream&, const Json&)
- Writes well-formed JSON text representing this object into std::ostream.
- friend std::istream& operator >> (std::istream&, Json&)
- Reads well-formed JSON text into given instance, replacing previous content.
- static int indent
- If not 0, result of formatting looks prettier.
- bool valid(Json& schema, std::string* reason = nullptr)
- Validates this instance against schema. If not valid and reason is not a null pointer, fills it with a short explanation of the problem.
- bool to_schema(std::string* reason)
- If this instance is a schema, tries to "compile" it, returning `false` and filling in reason if this is not a valid schema. Useful if this schema will be used for validation several times, otherwise every call of `valid()` will compile its argument again.
- size_t size() const
- Returns size of an array or number of properties for an object.
- static Json null
- The null instance.
- static Json array()
- Returns an empty array, that is [].
- static Json object()
- Returns an empty object, that is {}
Json class has value semantics. The following code:
Json arr { 1, 2, "three" };
Json three = arr[2];
arr.replace(2, 3); // or: arr.erase(2);
cout << three;
still prints "three". I hope this is what one would expect. On the other hand, if an array or object is a component of another array or object, changes in the component are visible "through", e.g.:
Json arr { 1, 2, "three" };
Json obj;
obj["arr"] = arr;
arr[2] = 3;
cout << obj["arr"][2]; // prints 3
Json class defines a static member Json::null of type JSNULL. It can be used to test for 'nullity' and for removing all contents from an object:
if (js == Json::null)
big_object = Json::null;
There is a difference between s1 and s2 in the following example:
Json hello = "hello";
string s1 = hello;
string s2 = hello.format();
The assignment to s1 is a cast, so the value of s1 is hello. The value of s2 is "hello" (with double quotes) because format
creates a well-formed JSON text and returns it as a string.
The project contains a toy command line application for viewing and editing JSON files. Just compile and run clison.cpp. The dialog looks like this:
at top: object
0. web-app {3}
> 0
.web-app: object
0. servlet [5]
1. servlet-mapping {5}
2. taglib {2}
> 2
.web-app.taglib: object
0. taglib-uri: "cofax.tld"
1. taglib-location: "/WEB-INF/tlds/cofax.tld"
> h
enter a number to select an object, q to go back
. : list current object
p [file.json] : print out current object [into file]
s file.json : load file as a json schema
= text : replace current object by parsed text
>