README.md 67.8 KB
Newer Older
Niels's avatar
Niels committed
1
[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases)
Niels's avatar
Niels committed
2

Niels's avatar
Niels committed
3
[![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json)
4
[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
Niels's avatar
Niels committed
5
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
6
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
7
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade)
Niels Lohmann's avatar
Niels Lohmann committed
8
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp)
9
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/TarF5pPn9NtHQjhf)
Niels's avatar
Niels committed
10
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
Niels's avatar
Niels committed
11
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
12
13
[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
[![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues)
14
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/nlohmann/json.svg)](http://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue")
15
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289)
Niels's avatar
Niels committed
16

17
18
- [Design goals](#design-goals)
- [Integration](#integration)
19
20
  - [CMake](#cmake)
  - [Package Managers](#package-managers)
21
22
23
24
25
26
- [Examples](#examples)
  - [JSON as first-class data type](#json-as-first-class-data-type)
  - [Serialization / Deserialization](#serialization--deserialization)
  - [STL-like access](#stl-like-access)
  - [Conversion from STL containers](#conversion-from-stl-containers)
  - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch)
27
  - [JSON Merge Patch](#json-merge-patch)
28
  - [Implicit conversions](#implicit-conversions)
Niels Lohmann's avatar
Niels Lohmann committed
29
  - [Conversions to/from arbitrary types](#arbitrary-types-conversions)
30
  - [Specializing enum conversion](#specializing-enum-conversion)
31
  - [Binary formats (BSON, CBOR, MessagePack, and UBJSON)](#binary-formats-bson-cbor-messagepack-and-ubjson)
32
33
- [Supported compilers](#supported-compilers)
- [License](#license)
34
- [Contact](#contact)
35
- [Thanks](#thanks)
36
- [Used third-party tools](#used-third-party-tools)
37
- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c)
38
39
40
- [Notes](#notes)
- [Execute unit tests](#execute-unit-tests)

Niels's avatar
Niels committed
41
42
43
44
## 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:

45
- **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 you'll know what I mean.
Niels's avatar
Niels committed
46

47
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
Niels's avatar
Niels committed
48

Manvendra Singh's avatar
Manvendra Singh committed
49
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/test/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289).
Niels's avatar
Niels committed
50
51
52

Other aspects were not so important to us:

Niels's avatar
Niels committed
53
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
Niels's avatar
Niels committed
54

Niels Lohmann's avatar
Niels Lohmann committed
55
- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set.
Niels's avatar
Niels committed
56

Niels's avatar
cleanup    
Niels committed
57
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
Niels's avatar
Niels committed
58

Niels's avatar
Niels committed
59

Niels's avatar
Niels committed
60
61
## Integration

Niels Lohmann's avatar
Niels Lohmann committed
62
[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add
Niels's avatar
Niels committed
63
64

```cpp
Patrik Huber's avatar
Patrik Huber committed
65
#include <nlohmann/json.hpp>
Niels's avatar
Niels committed
66
67
68
69
70

// for convenience
using json = nlohmann::json;
```

Wilson's avatar
Wilson committed
71
to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).
Niels's avatar
Niels committed
72

Wilson's avatar
Wilson committed
73
You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of json_fwd.hpp (as part of cmake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`.
74

75
76
77
78
79
80
81
### CMake

You can also use the `nlohmann_json::nlohmann_json` interface target in CMake.  This target populates the appropriate usage requirements for `INTERFACE_INCLUDE_DIRECTORIES` to point to the appropriate include directories and `INTERFACE_COMPILE_FEATURES` for the necessary C++11 flags.

#### External

To use this library from a CMake project, you can locate it directly with `find_package()` and use the namespaced imported target from the generated package configuration:
82
83
```cmake
# CMakeLists.txt
84
find_package(nlohmann_json 3.2.0 REQUIRED)
85
86
87
88
89
90
91
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of the build tree.

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#### Embedded

To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call `add_subdirectory()` in your `CMakeLists.txt` file:
```cmake
# Typically you don't care so much for a third party library's tests to be
# run from your own project's code.
set(JSON_BuildTests OFF CACHE INTERNAL "")

# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it
# inintended consequences that will break the build.  It's generally
# discouraged (although not necessarily well documented as such) to use
# include(...) for pulling in other CMake projects anyways.
add_subdirectory(nlohmann_json)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```

#### Supporting Both
To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin to the following:
``` cmake
# Top level CMakeLists.txt
project(FOO)
...
option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF)
...
add_subdirectory(thirdparty)
...
add_library(foo ...)
...
# Note that the namespaced target will always be available regardless of the
# import method
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
```cmake
# thirdparty/CMakeLists.txt
...
if(FOO_USE_EXTERNAL_JSON)
  find_package(nlohmann_json 3.2.0 REQUIRED)
else()
  set(JSON_BuildTests OFF CACHE INTERNAL "")
  add_subdirectory(nlohmann_json)
endif()
...
```
`thirdparty/nlohmann_json` is then a complete copy of this source tree.
139

140
141
### Package Managers

142
:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`.
Niels's avatar
Niels committed
143

144
If you are using the [Meson Build System](http://mesonbuild.com), then you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`.
Jay Sistar's avatar
Jay Sistar committed
145

146
147
If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `jsonformoderncpp/x.y.z@vthiery/stable` to your `conanfile.py`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/vthiery/conan-jsonformoderncpp/issues) if you experience problems with the packages.

Axel Huebl's avatar
Axel Huebl committed
148
149
If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the `nlohmann_json` package. Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging.

Jorrit Wronski's avatar
Jorrit Wronski committed
150
If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
gregmarr's avatar
gregmarr committed
151

152
153
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json).

gregmarr's avatar
gregmarr committed
154
If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json). Please see the vcpkg project for any issues regarding the packaging.
155

Wilson's avatar
Wilson committed
156
If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`).
157

158
159
If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open).

Niels's avatar
Niels committed
160
161
## Examples

162
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
163

164
165
### JSON as first-class data type

Niels's avatar
Niels committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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
  }
}
```

Niels Lohmann's avatar
Niels Lohmann committed
187
With this library, you could write:
Niels's avatar
Niels committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

```cpp
// create an empty structure (null)
json j;

// add a number that is stored as double (note the implicit conversion of j to an object)
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 another null object by passing nullptr
j["nothing"] = nullptr;

// add an object inside the object
j["answer"]["everything"] = 42;

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

// add another object (using an initializer list of pairs)
j["object"] = { {"currency", "USD"}, {"value", 42.99} };

// 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}
  }}
};
```

Niels Lohmann's avatar
Niels Lohmann committed
231
Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa80485befaffcadaa39965494e0b4d2e.html#aa80485befaffcadaa39965494e0b4d2e) and [`json::object`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa13f7c0615867542ce80337cbcf13ada.html#aa13f7c0615867542ce80337cbcf13ada) will help:
Niels's avatar
Niels committed
232
233

```cpp
Niels's avatar
Niels committed
234
// a way to express the empty array []
Niels's avatar
Niels committed
235
236
json empty_array_explicit = json::array();

Niels's avatar
Niels committed
237
238
// ways to express the empty object {}
json empty_object_implicit = json({});
Niels's avatar
Niels committed
239
240
241
json empty_object_explicit = json::object();

// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
242
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
Niels's avatar
Niels committed
243
244
245
246
```

### Serialization / Deserialization

Niels Lohmann's avatar
Niels Lohmann committed
247
248
#### To/from strings

Niels Lohmann's avatar
Niels Lohmann committed
249
You can create a JSON value (deserialization) by appending `_json` to a string literal:
Niels's avatar
Niels committed
250
251
252
253
254

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

Niels's avatar
Niels committed
255
// or even nicer with a raw string literal
Niels's avatar
Niels committed
256
257
258
259
260
261
auto j2 = R"(
  {
    "happy": true,
    "pi": 3.141
  }
)"_json;
262
263
```

Niels Lohmann's avatar
Niels Lohmann committed
264
Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object.
Niels's avatar
Niels committed
265

Niels Lohmann's avatar
Niels Lohmann committed
266
The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa9676414f2e36383c4b181fe856aa3c0.html#aa9676414f2e36383c4b181fe856aa3c0):
267
268
269

```cpp
// parse explicitly
Niels's avatar
Niels committed
270
271
272
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
```

Niels Lohmann's avatar
Niels Lohmann committed
273
You can also get a string representation of a JSON value (serialize):
Niels's avatar
Niels committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287

```cpp
// explicit conversion to string
std::string s = j.dump();    // {\"happy\":true,\"pi\":3.141}

// serialization with pretty printing
// pass in the amount of spaces to indent
std::cout << j.dump(4) << std::endl;
// {
//     "happy": true,
//     "pi": 3.141
// }
```

288
289
290
291
292
293
Note the difference between serialization and assignment:

```cpp
// store a string in a JSON value
json j_string = "this is a string";

294
295
296
297
298
// retrieve the string value
auto cpp_string = j_string.get<std::string>();
// retrieve the string value (alternative when an variable already exists)
std::string cpp_string2;
j_string.get_to(cpp_string2);
299
300
301
302
303

// retrieve the serialized value (explicit JSON serialization)
std::string serialized_string = j_string.dump();

// output of original string
304
std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
305
306
307
308
// output of serialized value
std::cout << j_string << " == " << serialized_string << std::endl;
```

309
[`.dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) always returns the serialized value, and [`.get<std::string>()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a16f9445f7629f634221a42b967cdcd43.html#a16f9445f7629f634221a42b967cdcd43) returns the originally stored string value.
310

311
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
312

Niels Lohmann's avatar
Niels Lohmann committed
313
314
#### To/from streams (e.g. files, string streams)

Niels's avatar
Niels committed
315
316
317
318
319
You can also use streams to serialize and deserialize:

```cpp
// deserialize from standard input
json j;
Niels's avatar
Niels committed
320
std::cin >> j;
Niels's avatar
Niels committed
321
322
323
324
325
326
327
328

// serialize to standard output
std::cout << j;

// the setw manipulator was overloaded to set the indentation for pretty printing
std::cout << std::setw(4) << j << std::endl;
```

Niels Lohmann's avatar
Niels Lohmann committed
329
330
331
332
333
334
335
336
337
338
339
340
These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files:

```cpp
// read a JSON file
std::ifstream i("file.json");
json j;
i >> j;

// write prettified JSON to another file
std::ofstream o("pretty.json");
o << std::setw(4) << j << std::endl;
```
Niels's avatar
Niels committed
341

Kevin Dixon's avatar
Kevin Dixon committed
342
343
Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use.

Niels Lohmann's avatar
Niels Lohmann committed
344
345
#### Read from iterator range

Niels Lohmann's avatar
Niels Lohmann committed
346
You can also parse JSON from an iterator range; that is, from any container accessible by iterators whose content is stored as contiguous byte sequence, for instance a `std::vector<std::uint8_t>`:
Niels Lohmann's avatar
Niels Lohmann committed
347
348

```cpp
349
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
Niels Lohmann's avatar
Niels Lohmann committed
350
351
352
353
354
355
json j = json::parse(v.begin(), v.end());
```

You may leave the iterators for the range [begin, end):

```cpp
356
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
Niels Lohmann's avatar
Niels Lohmann committed
357
358
359
json j = json::parse(v);
```

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#### SAX interface

The library uses a SAX-like interface with the following functions:

```cpp
// called when null is parsed
bool null();

// called when a boolean is parsed; value is passed
bool boolean(bool val);

// called when a signed or unsigned integer number is parsed; value is passed
bool number_integer(number_integer_t val);
bool number_unsigned(number_unsigned_t val);

// called when a floating-point number is parsed; value and original string is passed
bool number_float(number_float_t val, const string_t& s);

// called when a string is parsed; value is passed and can be safely moved away
bool string(string_t& val);

// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
bool start_object(std::size_t elements);
bool end_object();
bool start_array(std::size_t elements);
bool end_array();
// called when an object key is parsed; value is passed and can be safely moved away
bool key(string_t& val);

// called when a parse error occurs; byte position, the last token, and an exception is passed
bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
```

The return value of each function determines whether parsing should proceed.

To implement your own SAX handler, proceed as follows:

1. Implement the SAX interface in a class. You can use class `nlohmann::json_sax<json>` as base class, but you can also use any class where the functions described above are implemented and public.
2. Create an object of your SAX interface class, e.g. `my_sax`.
3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.

Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a  `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).

Niels's avatar
Niels committed
403

Niels's avatar
Niels committed
404
405
### STL-like access

406
We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) requirement.
Niels's avatar
Niels committed
407
408
409
410
411
412
413
414

```cpp
// create an array using push_back
json j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);

Niels Lohmann's avatar
Niels Lohmann committed
415
416
417
// also use emplace_back
j.emplace_back(1.78);

Niels's avatar
Niels committed
418
419
420
421
422
423
// iterate the array
for (json::iterator it = j.begin(); it != j.end(); ++it) {
  std::cout << *it << '\n';
}

// range-based for
Niels's avatar
Niels committed
424
for (auto& element : j) {
Niels's avatar
Niels committed
425
426
427
428
  std::cout << element << '\n';
}

// getter/setter
429
const auto tmp = j[0].get<std::string>();
Niels's avatar
Niels committed
430
431
432
j[1] = 42;
bool foo = j.at(2);

Jonathan Lee's avatar
Jonathan Lee committed
433
434
435
// comparison
j == "[\"foo\", 1, true]"_json;  // true

Niels's avatar
Niels committed
436
437
438
439
440
441
// other stuff
j.size();     // 3 entries
j.empty();    // false
j.type();     // json::value_t::array
j.clear();    // the array is empty again

Niels's avatar
Niels committed
442
443
444
445
446
447
448
449
// convenience type checkers
j.is_null();
j.is_boolean();
j.is_number();
j.is_object();
j.is_array();
j.is_string();

Niels's avatar
Niels committed
450
451
452
453
454
455
// create an object
json o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;

Niels Lohmann's avatar
Niels Lohmann committed
456
457
458
// also use emplace
o.emplace("weather", "sunny");

Niels's avatar
Niels committed
459
460
461
462
463
// special iterator member functions for objects
for (json::iterator it = o.begin(); it != o.end(); ++it) {
  std::cout << it.key() << " : " << it.value() << "\n";
}

Niels's avatar
Niels committed
464
465
466
467
// find an entry
if (o.find("foo") != o.end()) {
  // there is an entry with key "foo"
}
Niels's avatar
Niels committed
468
469
470
471
472
473
474

// or simpler using count()
int foo_present = o.count("foo"); // 1
int fob_present = o.count("fob"); // 0

// delete an entry
o.erase("foo");
Niels's avatar
Niels committed
475
476
```

Niels's avatar
Niels committed
477

Niels's avatar
Niels committed
478
479
### Conversion from STL containers

Niels Lohmann's avatar
Niels Lohmann committed
480
Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON values (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends on how the elements are ordered in the respective STL container.
Niels's avatar
Niels committed
481
482
483
484
485
486

```cpp
std::vector<int> c_vector {1, 2, 3, 4};
json j_vec(c_vector);
// [1, 2, 3, 4]

Niels's avatar
Niels committed
487
std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6};
Niels's avatar
Niels committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
json j_deque(c_deque);
// [1.2, 2.3, 3.4, 5.6]

std::list<bool> c_list {true, true, false, true};
json j_list(c_list);
// [true, true, false, true]

std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
json j_flist(c_flist);
// [12345678909876, 23456789098765, 34567890987654, 45678909876543]

std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
json j_array(c_array);
// [1, 2, 3, 4]

std::set<std::string> c_set {"one", "two", "three", "four", "one"};
json j_set(c_set); // only one entry for "one" is used
// ["four", "one", "three", "two"]

std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
json j_uset(c_uset); // only one entry for "one" is used
// maybe ["two", "three", "four", "one"]

std::multiset<std::string> c_mset {"one", "two", "one", "four"};
512
513
json j_mset(c_mset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
Niels's avatar
Niels committed
514
515
516
517
518
519

std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
json j_umset(c_umset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
```

Niels Lohmann's avatar
Niels Lohmann committed
520
Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON values (see examples above) can be used to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container.
Niels's avatar
Niels committed
521
522
523
524

```cpp
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
json j_map(c_map);
Annihil's avatar
Annihil committed
525
// {"one": 1, "three": 3, "two": 2 }
Niels's avatar
Niels committed
526

Niels's avatar
Niels committed
527
std::unordered_map<const char*, double> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };
Niels's avatar
Niels committed
528
529
530
531
532
533
534
535
536
537
538
539
json j_umap(c_umap);
// {"one": 1.2, "two": 2.3, "three": 3.4}

std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
json j_mmap(c_mmap); // only one entry for key "three" is used
// maybe {"one": true, "two": true, "three": true}

std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
json j_ummap(c_ummap); // only one entry for key "three" is used
// maybe {"one": true, "two": true, "three": true}
```

Niels's avatar
Niels committed
540
541
542
543
544
545
546
547
548
549
550
551
### JSON Pointer and JSON Patch

The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. On top of this, **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) allows to describe differences between two JSON values - effectively allowing patch and diff operations known from Unix.

```cpp
// a JSON value
json j_original = R"({
  "baz": ["one", "two", "three"],
  "foo": "bar"
})"_json;

// access members with a JSON pointer (RFC 6901)
Niels's avatar
Niels committed
552
j_original["/baz/1"_json_pointer];
Niels's avatar
Niels committed
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
// "two"

// a JSON patch (RFC 6902)
json j_patch = R"([
  { "op": "replace", "path": "/baz", "value": "boo" },
  { "op": "add", "path": "/hello", "value": ["world"] },
  { "op": "remove", "path": "/foo"}
])"_json;

// apply the patch
json j_result = j_original.patch(j_patch);
// {
//    "baz": "boo",
//    "hello": ["world"]
// }

// calculate a JSON patch from two JSON values
json::diff(j_result, j_original);
// [
//   { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
Niels's avatar
Niels committed
573
574
//   { "op": "remove","path": "/hello" },
//   { "op": "add", "path": "/foo", "value": "bar" }
Niels's avatar
Niels committed
575
576
577
// ]
```

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
### JSON Merge Patch

The library supports **JSON Merge Patch** ([RFC 7386](https://tools.ietf.org/html/rfc7386)) as a patch format. Instead of using JSON Pointer (see above) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified.

```cpp
// a JSON value
json j_document = R"({
  "a": "b",
  "c": {
    "d": "e",
    "f": "g"
  }
})"_json;

// a patch
json j_patch = R"({
  "a":"z",
  "c": {
    "f": null
  }
})"_json;

// apply the patch
j_original.merge_patch(j_patch);
// {
//  "a": "z",
//  "c": {
//    "d": "e"
//  }
// }
```
Niels's avatar
Niels committed
609

Niels's avatar
Niels committed
610
611
### Implicit conversions

612
613
614
Supported types can be implicitly converted to JSON values.

It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
kjpus's avatar
kjpus committed
615
You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958). 
Niels's avatar
Niels committed
616
617

```cpp
Niels's avatar
Niels committed
618
// strings
Niels's avatar
Niels committed
619
620
std::string s1 = "Hello, world!";
json js = s1;
621
622
623
624
625
auto s2 = js.get<std::string>();
// NOT RECOMMENDED
std::string s3 = js;
std::string s4;
s4 = js;
Niels's avatar
Niels committed
626
627
628
629

// Booleans
bool b1 = true;
json jb = b1;
630
631
632
633
634
auto b2 = jb.get<bool>();
// NOT RECOMMENDED
bool b3 = jb;
bool b4;
b4 = jb;
Niels's avatar
Niels committed
635
636
637
638

// numbers
int i = 42;
json jn = i;
639
640
641
642
643
auto f = jn.get<double>();
// NOT RECOMMENDED
double f2 = jb;
double f3;
f3 = jb;
Niels's avatar
Niels committed
644
645
646

// etc.
```
Niels Lohmann's avatar
Niels Lohmann committed
647

Niels Lohmann's avatar
Niels Lohmann committed
648
649
650
651
652
653
654
655
Note that `char` types are not automatically converted to JSON strings, but to integer numbers. A conversion to a string must be specified explicitly:

```cpp
char ch = 'A';                       // ASCII value 65
json j_default = ch;                 // stores integer number 65
json j_string = std::string(1, ch);  // stores string "A"
```

Théo DELRIEU's avatar
Théo DELRIEU committed
656
657
### Arbitrary types conversions

Niels Lohmann's avatar
Niels Lohmann committed
658
Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines:
Théo DELRIEU's avatar
Théo DELRIEU committed
659
660
661

```cpp
namespace ns {
Niels Lohmann's avatar
Niels Lohmann committed
662
    // a simple struct to model a person
Niels Lohmann's avatar
Niels Lohmann committed
663
664
665
666
667
    struct person {
        std::string name;
        std::string address;
        int age;
    };
Théo DELRIEU's avatar
Théo DELRIEU committed
668
}
Niels Lohmann's avatar
Niels Lohmann committed
669

Niels Lohmann's avatar
Niels Lohmann committed
670
671
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

Niels Lohmann's avatar
Niels Lohmann committed
672
// convert to JSON: copy each value into the JSON object
Théo DELRIEU's avatar
Théo DELRIEU committed
673
674
675
676
677
678
679
json j;
j["name"] = p.name;
j["address"] = p.address;
j["age"] = p.age;

// ...

Niels Lohmann's avatar
Niels Lohmann committed
680
// convert from JSON: copy each value from the JSON object
Niels Lohmann's avatar
Niels Lohmann committed
681
682
683
684
685
ns::person p {
    j["name"].get<std::string>(),
    j["address"].get<std::string>(),
    j["age"].get<int>()
};
Théo DELRIEU's avatar
Théo DELRIEU committed
686
687
```

Niels Lohmann's avatar
Niels Lohmann committed
688
It works, but that's quite a lot of boilerplate... Fortunately, there's a better way:
Théo DELRIEU's avatar
Théo DELRIEU committed
689
690

```cpp
Niels Lohmann's avatar
Niels Lohmann committed
691
692
693
694
// create a person
ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};

// conversion: person -> json
Théo DELRIEU's avatar
Théo DELRIEU committed
695
696
json j = p;

Niels Lohmann's avatar
Niels Lohmann committed
697
698
699
700
std::cout << j << std::endl;
// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}

// conversion: json -> person
701
auto p2 = j.get<ns::person>();
Niels Lohmann's avatar
Niels Lohmann committed
702
703

// that's it
Théo DELRIEU's avatar
Théo DELRIEU committed
704
705
706
707
708
assert(p == p2);
```

#### Basic usage

Niels Lohmann's avatar
Niels Lohmann committed
709
To make this work with one of your types, you only need to provide two functions:
Théo DELRIEU's avatar
Théo DELRIEU committed
710
711
712
713
714

```cpp
using nlohmann::json;

namespace ns {
Niels Lohmann's avatar
Niels Lohmann committed
715
    void to_json(json& j, const person& p) {
Niels Lohmann's avatar
Niels Lohmann committed
716
717
718
        j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
    }

Niels Lohmann's avatar
Niels Lohmann committed
719
    void from_json(const json& j, person& p) {
720
721
722
        j.at("name").get_to(p.name);
        j.at("address").get_to(p.address);
        j.at("age").get_to(p.age);
Niels Lohmann's avatar
Niels Lohmann committed
723
    }
Théo DELRIEU's avatar
Théo DELRIEU committed
724
725
726
} // namespace ns
```

Niels Lohmann's avatar
Niels Lohmann committed
727
That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
728
Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_json` method will be called.
Théo DELRIEU's avatar
Théo DELRIEU committed
729
730
731

Some important things:

Niels Lohmann's avatar
Niels Lohmann committed
732
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
733
* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
734
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
Itja's avatar
Itja committed
735
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
Niels Lohmann's avatar
Niels Lohmann committed
736
737
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.

Théo DELRIEU's avatar
Théo DELRIEU committed
738
739
740

#### How do I convert third-party types?

Niels Lohmann's avatar
Niels Lohmann committed
741
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
Théo DELRIEU's avatar
Théo DELRIEU committed
742
743

The library uses **JSON Serializers** to convert types to json.
744
The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)).
Théo DELRIEU's avatar
Théo DELRIEU committed
745
746
747
748
749

It is implemented like this (simplified):

```cpp
template <typename T>
Niels Lohmann's avatar
Niels Lohmann committed
750
751
752
753
754
755
756
757
struct adl_serializer {
    static void to_json(json& j, const T& value) {
        // calls the "to_json" method in T's namespace
    }

    static void from_json(const json& j, T& value) {
        // same thing, but with the "from_json" method
    }
Théo DELRIEU's avatar
Théo DELRIEU committed
758
759
760
};
```

Niels Lohmann's avatar
Niels Lohmann committed
761
This serializer works fine when you have control over the type's namespace. However, what about `boost::optional` or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`...
Théo DELRIEU's avatar
Théo DELRIEU committed
762
763
764
765
766
767

To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example:

```cpp
// partial specialization (full specialization works too)
namespace nlohmann {
Niels Lohmann's avatar
Niels Lohmann committed
768
769
770
771
772
773
    template <typename T>
    struct adl_serializer<boost::optional<T>> {
        static void to_json(json& j, const boost::optional<T>& opt) {
            if (opt == boost::none) {
                j = nullptr;
            } else {
Niels Lohmann's avatar
Niels Lohmann committed
774
775
              j = *opt; // this will call adl_serializer<T>::to_json which will
                        // find the free function to_json in T's namespace!
Niels Lohmann's avatar
Niels Lohmann committed
776
777
778
779
            }
        }

        static void from_json(const json& j, boost::optional<T>& opt) {
780
781
782
            if (j.is_null()) {
                opt = boost::none;
            } else {
Wilson's avatar
Wilson committed
783
                opt = j.get<T>(); // same as above, but with
Niels Lohmann's avatar
Niels Lohmann committed
784
785
786
787
                                  // adl_serializer<T>::from_json
            }
        }
    };
Théo DELRIEU's avatar
Théo DELRIEU committed
788
789
790
791
792
}
```

#### How can I use `get()` for non-default constructible/non-copyable types?

793
There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
Théo DELRIEU's avatar
Théo DELRIEU committed
794
795
796

```cpp
struct move_only_type {
Niels Lohmann's avatar
Niels Lohmann committed
797
798
799
800
    move_only_type() = delete;
    move_only_type(int ii): i(ii) {}
    move_only_type(const move_only_type&) = delete;
    move_only_type(move_only_type&&) = default;
Wilson's avatar
Wilson committed
801

Niels Lohmann's avatar
Niels Lohmann committed
802
    int i;
Théo DELRIEU's avatar
Théo DELRIEU committed
803
804
805
};

namespace nlohmann {
Niels Lohmann's avatar
Niels Lohmann committed
806
807
    template <>
    struct adl_serializer<move_only_type> {
Niels Lohmann's avatar
Niels Lohmann committed
808
809
        // note: the return type is no longer 'void', and the method only takes
        // one argument
Niels Lohmann's avatar
Niels Lohmann committed
810
811
812
        static move_only_type from_json(const json& j) {
            return {j.get<int>()};
        }
Wilson's avatar
Wilson committed
813

Niels Lohmann's avatar
Niels Lohmann committed
814
815
816
        // Here's the catch! You must provide a to_json method! Otherwise you
        // will not be able to convert move_only_type to json, since you fully
        // specialized adl_serializer on that type
Niels Lohmann's avatar
Niels Lohmann committed
817
818
819
820
        static void to_json(json& j, move_only_type t) {
            j = t.i;
        }
    };
Théo DELRIEU's avatar
Théo DELRIEU committed
821
822
823
824
825
}
```

#### Can I write my own serializer? (Advanced use)

Niels Lohmann's avatar
Niels Lohmann committed
826
Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples.
Théo DELRIEU's avatar
Théo DELRIEU committed
827
828
829

If you write your own serializer, you'll need to do a few things:

Niels Lohmann's avatar
Niels Lohmann committed
830
831
832
- use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`)
- use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods
- use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL
Théo DELRIEU's avatar
Théo DELRIEU committed
833
834
835
836

Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL.

```cpp
Niels Lohmann's avatar
Niels Lohmann committed
837
838
839
840
841
842
843
844
845
846
847
// You should use void as a second template argument
// if you don't need compile-time checks on T
template<typename T, typename SFINAE = typename std::enable_if<sizeof(T) <= 32>::type>
struct less_than_32_serializer {
    template <typename BasicJsonType>
    static void to_json(BasicJsonType& j, T value) {
        // we want to use ADL, and call the correct to_json overload
        using nlohmann::to_json; // this method is called by adl_serializer,
                                 // this is where the magic happens
        to_json(j, value);
    }
Wilson's avatar
Wilson committed
848

Niels Lohmann's avatar
Niels Lohmann committed
849
850
851
852
853
854
    template <typename BasicJsonType>
    static void from_json(const BasicJsonType& j, T& value) {
        // same thing here
        using nlohmann::from_json;
        from_json(j, value);
    }
Théo DELRIEU's avatar
Théo DELRIEU committed
855
856
857
858
859
860
861
862
863
};
```

Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention:

```cpp
template <typename T, void>
struct bad_serializer
{
Niels Lohmann's avatar
Niels Lohmann committed
864
865
866
867
868
869
    template <typename BasicJsonType>
    static void to_json(BasicJsonType& j, const T& value) {
      // this calls BasicJsonType::json_serializer<T>::to_json(j, value);
      // if BasicJsonType::json_serializer == bad_serializer ... oops!
      j = value;
    }
Wilson's avatar
Wilson committed
870

Niels Lohmann's avatar
Niels Lohmann committed
871
872
873
874
875
876
    template <typename BasicJsonType>
    static void to_json(const BasicJsonType& j, T& value) {
      // this calls BasicJsonType::json_serializer<T>::from_json(j, value);
      // if BasicJsonType::json_serializer == bad_serializer ... oops!
      value = j.template get<T>(); // oops!
    }
Théo DELRIEU's avatar
Théo DELRIEU committed
877
878
};
```
Niels's avatar
Niels committed
879

880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
### Specializing enum conversion

By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be undefined or a different enum value than was originally intended.

It is possible to more precisely specify how a given enum is mapped to and from JSON as shown below:

```cpp
// example enum type declaration
enum TaskState {
    TS_STOPPED,
    TS_RUNNING,
    TS_COMPLETED,
    TS_INVALID=-1,
};

// map TaskState values to JSON as strings
NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, {
    {TS_INVALID, nullptr},
    {TS_STOPPED, "stopped"},
    {TS_RUNNING, "running"},
    {TS_COMPLETED, "completed"},
});
```

The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serilization code.

**Usage:**

```cpp
// enum to JSON as string
json j = TS_STOPPED;
assert(j == "stopped");

// json string to enum
json j3 = "running";
assert(j3.get<TaskState>() == TS_RUNNING);

// undefined json value to enum (where the first map entry above is the default)
json jPi = 3.14;
assert(jPi.get<TaskState>() == TS_INVALID );
```

Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above,
- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace), or the library will not be able to locate it and it will default to integer serialization.
- It MUST be available (e.g., proper headers must be included) everywhere you use the conversions.

Other Important points:
- When using `get<ENUM_TYPE>()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully.
- If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON.

930
### Binary formats (BSON, CBOR, MessagePack, and UBJSON
931

Niels Lohmann's avatar
Niels Lohmann committed
932
Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](http://bsonspec.org) (Binary JSON), [CBOR](http://cbor.io) (Concise Binary Object Representation), [MessagePack](http://msgpack.org), and [UBJSON](http://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors.
933
934
935
936
937

```cpp
// create a JSON value
json j = R"({"compact": true, "schema": 0})"_json;

Niels Lohmann's avatar
Niels Lohmann committed
938
939
940
941
942
943
944
945
// serialize to BSON
std::vector<std::uint8_t> v_bson = json::to_bson(j);

// 0x1B, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x00, 0x01, 0x10, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

// roundtrip
json j_from_bson = json::from_bson(v_bson);

946
// serialize to CBOR
947
std::vector<std::uint8_t> v_cbor = json::to_cbor(j);
948

Niels Lohmann's avatar
Niels Lohmann committed
949
// 0xA2, 0x67, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xF5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00
950
951
952
953
954

// roundtrip
json j_from_cbor = json::from_cbor(v_cbor);

// serialize to MessagePack
955
std::vector<std::uint8_t> v_msgpack = json::to_msgpack(j);
956

Niels Lohmann's avatar
Niels Lohmann committed
957
// 0x82, 0xA7, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xC3, 0xA6, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00
958
959
960

// roundtrip
json j_from_msgpack = json::from_msgpack(v_msgpack);
Niels Lohmann's avatar
Niels Lohmann committed
961
962
963
964
965
966
967
968

// serialize to UBJSON
std::vector<std::uint8_t> v_ubjson = json::to_ubjson(j);

// 0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D

// roundtrip
json j_from_ubjson = json::from_ubjson(v_ubjson);
969
970
```

Niels's avatar
Niels committed
971
972
973

## Supported compilers

Niels Lohmann's avatar
Niels Lohmann committed
974
Though it's 2018 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
Niels's avatar
Niels committed
975

976
- GCC 4.8 - 8.2 (and possibly later)
977
- Clang 3.4 - 6.1 (and possibly later)
978
- Intel C++ Compiler 17.0.2 (and possibly later)
Niels's avatar
Niels committed
979
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
Niels Lohmann's avatar
Niels Lohmann committed
980
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
Niels's avatar
Niels committed
981
982
983
984
985

I would be happy to learn about other compilers/versions.

Please note:

986
- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler.
Niels's avatar
Niels committed
987
- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
Wilson's avatar
Wilson committed
988

Niels's avatar
Niels committed
989
990
991
992
993
    ```
    APP_STL := c++_shared
    NDK_TOOLCHAIN_VERSION := clang3.6
    APP_CPPFLAGS += -frtti -fexceptions
    ```
Wilson's avatar
Wilson committed
994

Niels's avatar
Niels committed
995
996
997
998
    The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10.

- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code,  but rather with the compiler itself. On Android, see above to build with a newer environment.  For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).

999
1000
- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case.