Find a file
Niels 9a567d9d2d - tidied code
- added more documentation
2013-07-11 14:19:11 +02:00
src - tidied code 2013-07-11 14:19:11 +02:00
test - reorganized payload 2013-07-10 14:33:17 +02:00
.gitignore - a config file for travis 2013-07-04 10:54:16 +02:00
.travis.yml - a config file for travis 2013-07-04 10:54:16 +02:00
configure.ac - removing Autoconf version requirement to allow travis to work 2013-07-04 17:13:04 +02:00
Makefile.am - initial commit 2013-07-04 10:49:03 +02:00
README.md - tidied code 2013-07-11 14:19:11 +02:00

Yet another JSON class for C++

Build Status

Design goals

There are myriads of JSON libraries out there, and each may even have its reason to exist. Our class had these design goals:

  • Trivial integration. Our whole code consists of just two files: A header file JSON.h and a source file JSON.cc. That's it. No library, no subproject, no dependencies. The class is written in vanilla C++98 and -- if possible -- uses some features of C++11 such as move constructors. All in all, the class should require no adjustment of your compiler flags or project settings.

  • Intiuitve syntax. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of C++ to achieve the same feeling in your code. Check out the examples below and you know, what I mean.

Other aspects were not so important to us:

  • Memory efficiency. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). We use the following C++ data types: std::string for strings, int or double for numbers, std::map for objects, std::vector for arrays, and bool for Booleans. We know that there are more efficient ways to store the values, but we are happy enough right now. And by the way: Valgrind says our code is free of leaks.

  • Speed. We currently implement the parser as naive recursive descent parser with hand coded string handling. It is fast enough, but a LALR-parser with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).

  • Rigourous standard compliance. We followed the specification as close as possible, but did not invest too much in a 100% compliance with respect to Unicode support. As a result, there might be edge cases of false positives and false negatives, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.

Integration

All you need to do is add

#include "JSON.h"

to the files you want to use JSON objects. Furthermore, you need to compile the file JSON.cc and link it to your binaries.

Examples

Here are some examples to give you an idea how to use the class:

// create an empty structure
JSON j;

// add a number that is stored as double
j["pi"] = 3.141;

// add a Boolean that is stored as bool
j["happy"] = true;

// add a string that is stored as std::string
j["name"] = "Niels";

// add an object inside the object
j["further"]["entry"] = 42;

// add an array that is stored as std::vector (C++11)
j["list"] = { 1, 0, 2 };

Input / Output

// create object from stream
JSON j;
j << "{ \"pi\": 3.141, \"happy\": true }";

// write string representation to stream
std::cout << j;

These operators work for any subclases of std::istream or std::ostream.

STL-like access

// create an array
JSON j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);

// iterate the array
for (JSON::iterator it = j.begin(); it != j.end(); ++it) {
  std::cout << *it << '\n';
}

// C++11 style
for (auto element : j) {
  std::cout << element << '\n';
}

// getter/setter
std::string tmp = j[0];
j[1] = 42;

// other stuff
j.size();     // 3
j.empty();    // false
j.type();     // JSON::array

// create an object
JSON o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;

// find an entry
if (o.find("foo") != o.end()) {
  // there is an entry with key "foo"
}

// iterate the object
for (JSON::iterator it = o.begin(); it != o.end(); ++it) {
  std::cout << it.key() << ':' << it.value() << '\n';
}

Implicit conversions

The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted

/// strings
std::string s1 = "Hello, world!";
JSON js = s;
std::string s2 = j;

// Booleans
bool b1 = true;
JSON jb = b1;
bool b2 = jb;

// numbers
int i = 42;
JSON jn = i;
double f = jn;