README.md 7.6 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/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 39 40 41

## Examples

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

```cpp
N
Niels 已提交
42
// create an empty structure (null)
N
Niels 已提交
43 44
JSON j;

N
Niels 已提交
45
// add a number that is stored as double (note the implicit conversion of j to an object)
N
Niels 已提交
46 47 48 49 50 51 52 53
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 已提交
54
// add another null object by passing nullptr
N
Niels 已提交
55 56
j["nothing"] = nullptr;

N
Niels 已提交
57
// add an object inside the object
N
Niels 已提交
58
j["answer"]["everything"] = 42;
N
Niels 已提交
59

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

N
Niels 已提交
63
// add another object (using an initializer list of pairs)
N
Niels 已提交
64
j["object"] = { {"currency", "USD"}, {"value", "42.99"} };
N
Niels 已提交
65 66
```

N
Niels 已提交
67
Note that in all cases, the compiler derives the appropriate JSON value.
N
Niels 已提交
68

N
Niels 已提交
69 70 71
### Serialization / Deserialization

You can create an object (deserialization) by appending `_json` to a string literal:
N
Niels 已提交
72 73 74 75 76 77

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

N
Niels 已提交
78
You can also get a string representation (serialize):
N
Niels 已提交
79 80 81 82 83 84 85 86

```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 已提交
87
You can also use streams to serialize and deserialize:
N
Niels 已提交
88

N
Niels 已提交
89
```cpp
N
Niels 已提交
90
// deserialize from standard input
N
Niels 已提交
91
JSON j;
N
Niels 已提交
92
j << std::cin;
N
Niels 已提交
93

N
Niels 已提交
94
// serialize to standard output
N
Niels 已提交
95 96 97
std::cout << j;
```

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

N
Niels 已提交
100 101
### STL-like access

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

N
Niels 已提交
104
```cpp
N
Niels 已提交
105
// create an array using push_back
N
Niels 已提交
106 107 108 109 110 111 112 113 114 115
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 已提交
116
// range-based for
N
Niels 已提交
117 118 119 120
for (auto element : j) {
  std::cout << element << '\n';
}

N
Niels 已提交
121
// getter/setter
N
Niels 已提交
122
const std::string tmp = j[0];
N
Niels 已提交
123
j[1] = 42;
N
Niels 已提交
124
bool foo = j.at(2);
N
Niels 已提交
125 126

// other stuff
N
Niels 已提交
127
j.size();     // 3 entries
N
Niels 已提交
128
j.empty();    // false
N
Niels 已提交
129 130
j.type();     // JSON::value_type::array
j.clear();    // the array is empty again
N
Niels 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

// 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 已提交
147
```
N
Niels 已提交
148 149 150

### Implicit conversions

N
Niels 已提交
151
The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted.
N
Niels 已提交
152 153 154 155

```cpp
/// strings
std::string s1 = "Hello, world!";
N
Niels 已提交
156 157
JSON js = s1;
std::string s2 = js;
N
Niels 已提交
158 159 160 161 162 163 164 165 166 167

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

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

// etc.
N
Niels 已提交
170 171
```

N
Niels 已提交
172 173 174 175 176 177 178 179 180 181 182 183
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 已提交
184
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
N
Niels 已提交
185

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

N
Niels 已提交
188
Copyright &copy; 2013-2014 [Niels Lohmann](http://nlohmann.me)
N
Niels 已提交
189 190 191 192 193 194

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 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

## 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).