README.md 8.2 KB
Newer Older
N
Niels 已提交
1
# JSON for Modern C++
N
Niels 已提交
2

N
Niels 已提交
3 4
*What if JSON was party of modern C++?*

N
Niels 已提交
5
[![Build Status](https://travis-ci.org/nlohmann/json.png?branch=master)](https://travis-ci.org/nlohmann/json)
N
Niels 已提交
6
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
N
Niels 已提交
7
[![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues)
N
Niels 已提交
8

N
Niels 已提交
9 10 11 12
## Design goals

There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:

N
Niels 已提交
13
- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and the [reference](https://github.com/nlohmann/json/blob/master/doc/Reference.md), and you know, what I mean.
N
Niels 已提交
14

N
Niels 已提交
15 16 17
- **Trivial integration**. Our whole code consists of a class in 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++11. All in all, everything should require no adjustment of your compiler flags or project settings.

- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/JSON_unit.cc) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks.
N
Niels 已提交
18

N
Niels 已提交
19 20
Other aspects were not so important to us:

N
Niels 已提交
21
- **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.
N
Niels 已提交
22

N
Niels 已提交
23
- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).
N
Niels 已提交
24

N
Niels 已提交
25
- **Rigorous standard compliance**. Any [compliant](http://json.org) JSON file can be read by our class, and any output of the class is standard-compliant. However, we do not check for some details in the format of numbers and strings. For instance, `-0` will be treated as `0` whereas the standard forbids this. Furthermore, we allow for more escape symbols in strings as the JSON specification. While this may not be a problem in reality, we are aware of it, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
N
Niels 已提交
26 27 28 29 30 31 32 33 34

## Integration

All you need to do is add

```cpp
#include "JSON.h"
```

N
Niels 已提交
35
to the files you want to use JSON objects. Furthermore, you need to compile the file `JSON.cc` and link it to your binaries. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).
N
Niels 已提交
36 37 38

## Examples

N
Niels 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Here are some examples to give you an idea how to use the class.

Assume you want to create the JSON object

```json
{
  "pi": 3.141,
  "happy": true,
  "name": "Niels",
  "nothing": null,
  "answer": {
    "everything": 42
  },
  "list": [1, 0, 2],
  "object": {
    "currency": "USD",
    "value": "42.99"
  }
}
```

With the JSON class, you could write:
N
Niels 已提交
61 62

```cpp
N
Niels 已提交
63
// create an empty structure (null)
N
Niels 已提交
64 65
JSON j;

N
Niels 已提交
66
// add a number that is stored as double (note the implicit conversion of j to an object)
N
Niels 已提交
67 68 69 70 71 72 73 74
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";

N
Niels 已提交
75
// add another null object by passing nullptr
N
Niels 已提交
76 77
j["nothing"] = nullptr;

N
Niels 已提交
78
// add an object inside the object
N
Niels 已提交
79
j["answer"]["everything"] = 42;
N
Niels 已提交
80

N
Niels 已提交
81
// add an array that is stored as std::vector (using an initializer list)
N
Niels 已提交
82
j["list"] = { 1, 0, 2 };
N
Niels 已提交
83

N
Niels 已提交
84
// add another object (using an initializer list of pairs)
N
Niels 已提交
85
j["object"] = { {"currency", "USD"}, {"value", "42.99"} };
N
Niels 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

// instead, you could also write (which looks very similar to the JSON above)
JSON j2 = {
  {"pi", 3.141},
  {"happy", true},
  {"name", "Niels"},
  {"nothing", nullptr},
  {"answer", {
    {"everything", 42}
  }},
  {"list", {1, 0, 2}},
  {"object", {
    {"currency", "USD"},
    {"value", "42.99"}
  }}
};
N
Niels 已提交
102 103
```

N
Niels 已提交
104
Note that in all cases, you never need to "tell" the compiler which JSON value you want to use.
N
Niels 已提交
105

N
Niels 已提交
106 107 108
### Serialization / Deserialization

You can create an object (deserialization) by appending `_json` to a string literal:
N
Niels 已提交
109 110 111 112 113 114

```cpp
// create object from string literal
JSON j = "{ \"pi\": 3.141, \"happy\": true }"_json;
```

N
Niels 已提交
115
You can also get a string representation (serialize):
N
Niels 已提交
116 117 118 119 120 121 122 123

```cpp
// explicit conversion to string
std::string s = j.toString();
```

The value of s could be `{"pi": 3.141, "happy": true}`, but the order of the entries in the object is not fixed.

N
Niels 已提交
124
You can also use streams to serialize and deserialize:
N
Niels 已提交
125

N
Niels 已提交
126
```cpp
N
Niels 已提交
127
// deserialize from standard input
N
Niels 已提交
128
JSON j;
N
Niels 已提交
129
j << std::cin;
N
Niels 已提交
130

N
Niels 已提交
131
// serialize to standard output
N
Niels 已提交
132 133 134
std::cout << j;
```

N
Niels 已提交
135
These operators work for any subclasses of `std::istream` or `std::ostream`.
N
Niels 已提交
136

N
Niels 已提交
137 138
### STL-like access

N
Niels 已提交
139 140
We designed the JSON class to behave just like an STL container:

N
Niels 已提交
141
```cpp
N
Niels 已提交
142
// create an array using push_back
N
Niels 已提交
143 144 145 146 147 148 149 150 151 152
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';
}

N
Niels 已提交
153
// range-based for
N
Niels 已提交
154 155 156 157
for (auto element : j) {
  std::cout << element << '\n';
}

N
Niels 已提交
158
// getter/setter
N
Niels 已提交
159
const std::string tmp = j[0];
N
Niels 已提交
160
j[1] = 42;
N
Niels 已提交
161
bool foo = j.at(2);
N
Niels 已提交
162 163

// other stuff
N
Niels 已提交
164
j.size();     // 3 entries
N
Niels 已提交
165
j.empty();    // false
N
Niels 已提交
166 167
j.type();     // JSON::value_type::array
j.clear();    // the array is empty again
N
Niels 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

// 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';
}
N
Niels 已提交
184
```
N
Niels 已提交
185 186 187

### Implicit conversions

N
Niels 已提交
188
The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted.
N
Niels 已提交
189 190 191 192

```cpp
/// strings
std::string s1 = "Hello, world!";
N
Niels 已提交
193 194
JSON js = s1;
std::string s2 = js;
N
Niels 已提交
195 196 197 198 199 200 201 202 203 204

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

// numbers
int i = 42;
JSON jn = i;
double f = jn;
N
Niels 已提交
205 206

// etc.
N
Niels 已提交
207 208
```

N
Niels 已提交
209 210 211 212 213 214 215 216 217 218 219 220
You can also explicitly ask for the value:

```cpp
std::string vs = js.get<std::string>();
bool vb = jb.get<bool>();
int vi = jn.get<int>();

// etc.
```

## License

N
Niels 已提交
221
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
N
Niels 已提交
222

N
Niels 已提交
223
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
N
Niels 已提交
224

N
Niels 已提交
225
Copyright &copy; 2013-2014 [Niels Lohmann](http://nlohmann.me)
N
Niels 已提交
226 227 228 229 230 231

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
N
Niels 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

## Execute unit tests

To compile the unit tests, you need to execute

```sh
  autoreconf -i
  ./configure
  make
```

The unit tests can then be executed with

```sh
./json_unit
```

For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).