README.md 99.4 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

3
[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
4
5
6
[![Ubuntu](https://github.com/nlohmann/json/workflows/Ubuntu/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AUbuntu)
[![macOS](https://github.com/nlohmann/json/workflows/macOS/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AmacOS)
[![Windows](https://github.com/nlohmann/json/workflows/Windows/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AWindows)
Niels Lohmann's avatar
Niels Lohmann committed
7
[![Coverage Status](https://coveralls.io/repos/github/nlohmann/json/badge.svg?branch=develop)](https://coveralls.io/github/nlohmann/json?branch=develop)
8
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
9
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/e0d1a9d5d6fd46fcb655c4cb930bb3e8)](https://www.codacy.com/gh/nlohmann/json/dashboard?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade)
Niels Lohmann's avatar
Niels Lohmann committed
10
[![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)
11
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
12
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
Niels Lohmann's avatar
Niels Lohmann committed
13
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](https://nlohmann.github.io/json/doxygen/index.html)
Niels's avatar
Niels committed
14
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
15
[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
Niels Lohmann's avatar
Niels Lohmann committed
16
[![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases)
TotalCaesar659's avatar
TotalCaesar659 committed
17
18
[![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](https://github.com/nlohmann/json/issues)
[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/nlohmann/json.svg)](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue")
19
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289)
Niels Lohmann's avatar
Niels Lohmann committed
20
[![GitHub Sponsors](https://img.shields.io/badge/GitHub-Sponsors-ff69b4)](https://github.com/sponsors/nlohmann)
Carlos Gomes Martinho's avatar
Carlos Gomes Martinho committed
21

22
- [Design goals](#design-goals)
Niels Lohmann's avatar
Niels Lohmann committed
23
- [Sponsors](#sponsors)
24
- [Support](#support) ([documentation](https://json.nlohmann.me), [FAQ](https://json.nlohmann.me/home/faq/), [discussions](https://github.com/nlohmann/json/discussions), [API](https://json.nlohmann.me/api/basic_json/), [bug issues](https://github.com/nlohmann/json/issues))
25
26
27
28
29
30
- [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)
31
  - [JSON Merge Patch](#json-merge-patch)
32
  - [Implicit conversions](#implicit-conversions)
Niels Lohmann's avatar
Niels Lohmann committed
33
  - [Conversions to/from arbitrary types](#arbitrary-types-conversions)
34
  - [Specializing enum conversion](#specializing-enum-conversion)
35
  - [Binary formats (BSON, CBOR, MessagePack, and UBJSON)](#binary-formats-bson-cbor-messagepack-and-ubjson)
36
- [Supported compilers](#supported-compilers)
Niels Lohmann's avatar
Niels Lohmann committed
37
38
39
40
- [Integration](#integration)
  - [CMake](#cmake)
  - [Package Managers](#package-managers)
  - [Pkg-config](#pkg-config)
41
- [License](#license)
42
- [Contact](#contact)
43
- [Thanks](#thanks)
44
- [Used third-party tools](#used-third-party-tools)
45
- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c)
46
47
48
- [Notes](#notes)
- [Execute unit tests](#execute-unit-tests)

Niels's avatar
Niels committed
49
50
## Design goals

Antoine Cœur's avatar
Antoine Cœur committed
51
There are myriads of [JSON](https://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
Niels's avatar
Niels committed
52

53
- **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
54

55
- **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
56

TotalCaesar659's avatar
TotalCaesar659 committed
57
- **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](https://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
58
59
60

Other aspects were not so important to us:

Niels's avatar
Niels committed
61
- **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
62

Niels Lohmann's avatar
Niels Lohmann committed
63
- **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
64

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

Niels's avatar
Niels committed
67

Niels Lohmann's avatar
Niels Lohmann committed
68
69
70
71
72
73
74
## Sponsors

You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann).

### :label: Named Sponsors

- [Michael Hartmann](https://github.com/reFX-Mike)
Niels Lohmann's avatar
Niels Lohmann committed
75
- [Stefan Hagen](https://github.com/sthagen)
Niels Lohmann's avatar
Niels Lohmann committed
76
- [Steve Sperandeo](https://github.com/homer6)
Niels Lohmann's avatar
Niels Lohmann committed
77
- [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe)
Niels Lohmann's avatar
Niels Lohmann committed
78
- [Steve Wagner](https://github.com/ciroque)
Niels Lohmann's avatar
Niels Lohmann committed
79
80
81

Thanks everyone!

Niels Lohmann's avatar
Niels Lohmann committed
82
83
84
85
86
87
88
89
## Support

:question: If you have a **question**, please check if it is already answered in the [**FAQ**](https://json.nlohmann.me/home/faq/) or the [**Q&A**](https://github.com/nlohmann/json/discussions/categories/q-a) section. If not, please [**ask a new question**](https://github.com/nlohmann/json/discussions/new) there.

:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/doc/examples), or browse through the [**help pages**](https://json.nlohmann.me).

:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or the [**Doxygen documentation**](https://json.nlohmann.me/doxygen/index.html).

90
:bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as much information as possible to help us understand and reproduce your issue.
Niels Lohmann's avatar
Niels Lohmann committed
91

92
There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for the documentation browsers [Dash](https://kapeli.com/dash), [Velocity](https://velocity.silverlakesoftware.com), and [Zeal](https://zealdocs.org) that contains the full [documentation](https://json.nlohmann.me) as offline resource.
Niels Lohmann's avatar
Niels Lohmann committed
93

Niels's avatar
Niels committed
94
95
## Examples

96
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/api/basic_json/emplace/)). 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)).
97

98
99
### JSON as first-class data type

Niels's avatar
Niels committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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
121
With this library, you could write:
Niels's avatar
Niels committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

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

165
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/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help:
Niels's avatar
Niels committed
166
167

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

Niels's avatar
Niels committed
171
172
// ways to express the empty object {}
json empty_object_implicit = json({});
Niels's avatar
Niels committed
173
174
175
json empty_object_explicit = json::object();

// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
176
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
Niels's avatar
Niels committed
177
178
179
180
```

### Serialization / Deserialization

Niels Lohmann's avatar
Niels Lohmann committed
181
182
#### To/from strings

Niels Lohmann's avatar
Niels Lohmann committed
183
You can create a JSON value (deserialization) by appending `_json` to a string literal:
Niels's avatar
Niels committed
184
185
186
187
188

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

Niels's avatar
Niels committed
189
// or even nicer with a raw string literal
Niels's avatar
Niels committed
190
191
192
193
194
195
auto j2 = R"(
  {
    "happy": true,
    "pi": 3.141
  }
)"_json;
196
197
```

Niels Lohmann's avatar
Niels Lohmann committed
198
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
199

200
The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/):
201
202
203

```cpp
// parse explicitly
204
auto j3 = json::parse(R"({"happy": true, "pi": 3.141})");
Niels's avatar
Niels committed
205
206
```

Niels Lohmann's avatar
Niels Lohmann committed
207
You can also get a string representation of a JSON value (serialize):
Niels's avatar
Niels committed
208
209
210

```cpp
// explicit conversion to string
211
std::string s = j.dump();    // {"happy":true,"pi":3.141}
Niels's avatar
Niels committed
212
213
214
215
216
217
218
219
220
221

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

222
223
224
225
226
227
Note the difference between serialization and assignment:

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

228
229
// retrieve the string value
auto cpp_string = j_string.get<std::string>();
230
// retrieve the string value (alternative when a variable already exists)
231
232
std::string cpp_string2;
j_string.get_to(cpp_string2);
233
234
235
236
237

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

// output of original string
238
std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
239
240
241
242
// output of serialized value
std::cout << j_string << " == " << serialized_string << std::endl;
```

243
[`.dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) returns the originally stored string value.
244

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

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

Niels's avatar
Niels committed
249
250
251
252
253
You can also use streams to serialize and deserialize:

```cpp
// deserialize from standard input
json j;
Niels's avatar
Niels committed
254
std::cin >> j;
Niels's avatar
Niels committed
255
256
257
258
259
260
261
262

// 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
263
264
265
266
267
268
269
270
271
272
273
274
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
275

Kevin Dixon's avatar
Kevin Dixon committed
276
277
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
278
279
#### Read from iterator range

Francois Chabot's avatar
Francois Chabot committed
280
You can also parse JSON from an iterator range; that is, from any container accessible by iterators whose `value_type` is an integral type of 1, 2 or 4 bytes, which will be interpreted as UTF-8, UTF-16 and UTF-32 respectively. For instance, a `std::vector<std::uint8_t>`, or a `std::list<std::uint16_t>`:
Niels Lohmann's avatar
Niels Lohmann committed
281
282

```cpp
283
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
Niels Lohmann's avatar
Niels Lohmann committed
284
285
286
287
288
289
json j = json::parse(v.begin(), v.end());
```

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

```cpp
290
std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
Niels Lohmann's avatar
Niels Lohmann committed
291
292
293
json j = json::parse(v);
```

Francois Chabot's avatar
Francois Chabot committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#### Custom data source

Since the parse function accepts arbitrary iterator ranges, you can provide your own data sources by implementing the `LegacyInputIterator` concept.

```cpp
struct MyContainer {
  void advance();
  const char& get_current();
};

struct MyIterator {
    using difference_type = std::ptrdiff_t;
    using value_type = char;
    using pointer = const char*;
    using reference = const char&;
    using iterator_category = std::input_iterator_tag;

    MyIterator& operator++() {
        MyContainer.advance();
Francois Chabot's avatar
Francois Chabot committed
313
        return *this;
Francois Chabot's avatar
Francois Chabot committed
314
315
316
    }

    bool operator!=(const MyIterator& rhs) const {
317
        return rhs.target != target;
Francois Chabot's avatar
Francois Chabot committed
318
319
320
321
322
323
324
325
326
327
    }

    reference operator*() const {
        return target.get_current();
    }

    MyContainer* target = nullptr;
};

MyIterator begin(MyContainer& tgt) {
328
    return MyIterator{&tgt};
Francois Chabot's avatar
Francois Chabot committed
329
330
331
}

MyIterator end(const MyContainer&) {
332
    return {};
Francois Chabot's avatar
Francois Chabot committed
333
334
335
336
337
338
339
340
}

void foo() {
    MyContainer c;
    json j = json::parse(c);
}
```

341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#### 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);
361
362
// called when a binary value is parsed; value is passed and can be safely moved away
bool binary(binary_t& val);
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

// 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
386
387
### STL-like access

388
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
389
390
391
392
393
394
395
396

```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
397
398
399
// also use emplace_back
j.emplace_back(1.78);

Niels's avatar
Niels committed
400
401
402
403
404
405
// 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
406
for (auto& element : j) {
Niels's avatar
Niels committed
407
408
409
410
  std::cout << element << '\n';
}

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

Jonathan Lee's avatar
Jonathan Lee committed
415
// comparison
416
j == R"(["foo", 1, true, 1.78])"_json;  // true
Jonathan Lee's avatar
Jonathan Lee committed
417

Niels's avatar
Niels committed
418
// other stuff
419
j.size();     // 4 entries
Niels's avatar
Niels committed
420
421
422
423
j.empty();    // false
j.type();     // json::value_t::array
j.clear();    // the array is empty again

Niels's avatar
Niels committed
424
425
426
427
428
429
430
431
// 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
432
433
434
435
436
437
// create an object
json o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;

Niels Lohmann's avatar
Niels Lohmann committed
438
439
440
// also use emplace
o.emplace("weather", "sunny");

Niels's avatar
Niels committed
441
442
443
444
445
// special iterator member functions for objects
for (json::iterator it = o.begin(); it != o.end(); ++it) {
  std::cout << it.key() << " : " << it.value() << "\n";
}

Niels Lohmann's avatar
Niels Lohmann committed
446
447
448
449
450
451
452
453
454
455
// the same code as range for
for (auto& el : o.items()) {
  std::cout << el.key() << " : " << el.value() << "\n";
}

// even easier with structured bindings (C++17)
for (auto& [key, value] : o.items()) {
  std::cout << key << " : " << value << "\n";
}

Niels's avatar
Niels committed
456
// find an entry
457
458
459
460
461
if (o.contains("foo")) {
  // there is an entry with key "foo"
}

// or via find and an iterator
Niels's avatar
Niels committed
462
463
464
if (o.find("foo") != o.end()) {
  // there is an entry with key "foo"
}
Niels's avatar
Niels committed
465
466
467
468
469
470
471

// 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
472
473
```

Niels's avatar
Niels committed
474

Niels's avatar
Niels committed
475
476
### Conversion from STL containers

Niels Lohmann's avatar
Niels Lohmann committed
477
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
478
479
480
481
482
483

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

Niels's avatar
Niels committed
484
std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6};
Niels's avatar
Niels committed
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
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"};
509
510
json j_mset(c_mset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
Niels's avatar
Niels committed
511
512
513
514
515
516

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
517
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
518
519
520
521

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

Niels's avatar
Niels committed
524
std::unordered_map<const char*, double> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };
Niels's avatar
Niels committed
525
526
527
528
529
530
531
532
533
534
535
536
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
537
538
### JSON Pointer and JSON Patch

539
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 describing differences between two JSON values - effectively allowing patch and diff operations known from Unix.
Niels's avatar
Niels committed
540
541
542
543
544
545
546
547
548

```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
549
j_original["/baz/1"_json_pointer];
Niels's avatar
Niels committed
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
// "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
570
571
//   { "op": "remove","path": "/hello" },
//   { "op": "add", "path": "/foo", "value": "bar" }
Niels's avatar
Niels committed
572
573
574
// ]
```

575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
### 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
Isaac Nickaein's avatar
Isaac Nickaein committed
598
j_document.merge_patch(j_patch);
599
600
601
602
603
604
605
// {
//  "a": "z",
//  "c": {
//    "d": "e"
//  }
// }
```
Niels's avatar
Niels committed
606

Niels's avatar
Niels committed
607
608
### Implicit conversions

609
610
611
Supported types can be implicitly converted to JSON values.

It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
612
You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958).
Niels Lohmann's avatar
Niels Lohmann committed
613
You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` before including the `json.hpp` header. When using CMake, you can also achieve this by setting the option `JSON_ImplicitConversions` to `OFF`.
Niels's avatar
Niels committed
614
615

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

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

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

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

Niels Lohmann's avatar
Niels Lohmann committed
646
647
648
649
650
651
652
653
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
654
655
### Arbitrary types conversions

Niels Lohmann's avatar
Niels Lohmann committed
656
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
657
658
659

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

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

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

// ...

Niels Lohmann's avatar
Niels Lohmann committed
678
// convert from JSON: copy each value from the JSON object
Niels Lohmann's avatar
Niels Lohmann committed
679
680
681
682
683
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
684
685
```

Niels Lohmann's avatar
Niels Lohmann committed
686
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
687
688

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

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

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

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

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

#### Basic usage

Niels Lohmann's avatar
Niels Lohmann committed
707
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
708
709

```cpp
justanotheranonymoususer's avatar
justanotheranonymoususer committed
710
using json = nlohmann::json;
Théo DELRIEU's avatar
Théo DELRIEU committed
711
712

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

Niels Lohmann's avatar
Niels Lohmann committed
717
    void from_json(const json& j, person& p) {
718
719
720
        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
721
    }
Théo DELRIEU's avatar
Théo DELRIEU committed
722
723
724
} // namespace ns
```

Niels Lohmann's avatar
Niels Lohmann committed
725
That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
726
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
727
728
729

Some important things:

Niels Lohmann's avatar
Niels Lohmann committed
730
* 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).
Mark Beckwith's avatar
Mark Beckwith committed
731
* Those methods **MUST** be available (e.g., proper 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.
732
* 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.)
733
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) 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
734
735
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.

Niels Lohmann's avatar
Niels Lohmann committed
736
737
738
739
740
741
#### Simplify your life with macros

If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.

There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:

742
743
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members.
Niels Lohmann's avatar
Niels Lohmann committed
744
745
746
747
748
749
750
751
752

In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.

##### Examples

The `to_json`/`from_json` functions for the `person` struct above can be created with:

```cpp
namespace ns {
Niels Lohmann's avatar
Niels Lohmann committed
753
    NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
Niels Lohmann's avatar
Niels Lohmann committed
754
755
756
757
758
759
760
761
762
763
764
765
}
```

Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:

```cpp
namespace ns {
    class address {
      private:
        std::string street;
        int housenumber;
        int postcode;
766

Niels Lohmann's avatar
Niels Lohmann committed
767
      public:
Niels Lohmann's avatar
Niels Lohmann committed
768
        NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
Niels Lohmann's avatar
Niels Lohmann committed
769
770
771
    };
}
```
Théo DELRIEU's avatar
Théo DELRIEU committed
772
773
774

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

Niels Lohmann's avatar
Niels Lohmann committed
775
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
776
777

The library uses **JSON Serializers** to convert types to json.
778
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
779
780
781
782
783

It is implemented like this (simplified):

```cpp
template <typename T>
Niels Lohmann's avatar
Niels Lohmann committed
784
785
786
787
788
789
790
791
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
792
793
794
};
```

Niels Lohmann's avatar
Niels Lohmann committed
795
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
796
797
798
799
800
801

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
802
803
804
805
806
807
    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
808
809
              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
810
811
812
813
            }
        }

        static void from_json(const json& j, boost::optional<T>& opt) {
814
815
816
            if (j.is_null()) {
                opt = boost::none;
            } else {
Wilson's avatar
Wilson committed
817
                opt = j.get<T>(); // same as above, but with
Niels Lohmann's avatar
Niels Lohmann committed
818
819
820
821
                                  // adl_serializer<T>::from_json
            }
        }
    };
Théo DELRIEU's avatar
Théo DELRIEU committed
822
823
824
825
826
}
```

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

827
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
828
829
830

```cpp
struct move_only_type {
Niels Lohmann's avatar
Niels Lohmann committed
831
832
833
834
    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
835

Niels Lohmann's avatar
Niels Lohmann committed
836
    int i;
Théo DELRIEU's avatar
Théo DELRIEU committed
837
838
839
};

namespace nlohmann {
Niels Lohmann's avatar
Niels Lohmann committed
840
841
    template <>
    struct adl_serializer<move_only_type> {
Niels Lohmann's avatar
Niels Lohmann committed
842
843
        // note: the return type is no longer 'void', and the method only takes
        // one argument
Niels Lohmann's avatar
Niels Lohmann committed
844
845
846
        static move_only_type from_json(const json& j) {
            return {j.get<int>()};
        }
Wilson's avatar
Wilson committed
847

848
        // Here's the catch! You must provide a to_json method! Otherwise, you
Niels Lohmann's avatar
Niels Lohmann committed
849
850
        // 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
851
852
853
854
        static void to_json(json& j, move_only_type t) {
            j = t.i;
        }
    };
Théo DELRIEU's avatar
Théo DELRIEU committed
855
856
857
858
859
}
```

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

Niels Lohmann's avatar
Niels Lohmann committed
860
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
861
862
863

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

Niels Lohmann's avatar
Niels Lohmann committed
864
865
866
- 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
867
868
869
870

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
871
872
873
874
875
876
877
878
879
880
881
// 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
882

Niels Lohmann's avatar
Niels Lohmann committed
883
884
885
886
887
888
    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
889
890
891
892
893
894
895
896
897
};
```

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
898
899
900
901
902
903
    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
904

Niels Lohmann's avatar
Niels Lohmann committed
905
906
907
908
909
910
    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
911
912
};
```
Niels's avatar
Niels committed
913

914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
### 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"},
Matěj Plch's avatar
Matěj Plch committed
935
})
936
937
```

0xflotus's avatar
0xflotus committed
938
The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code.
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956

**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,
957
- `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.
958
959
960
961
962
963
- 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.

Niels Lohmann's avatar
Niels Lohmann committed
964
### Binary formats (BSON, CBOR, MessagePack, and UBJSON)
965

966
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](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors.
967
968
969
970
971

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

Niels Lohmann's avatar
Niels Lohmann committed
972
973
974
975
976
977
978
979
// 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);

980
// serialize to CBOR
981
std::vector<std::uint8_t> v_cbor = json::to_cbor(j);
982

Niels Lohmann's avatar
Niels Lohmann committed
983
// 0xA2, 0x67, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xF5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00
984
985
986
987
988

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

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

Niels Lohmann's avatar
Niels Lohmann committed
991
// 0x82, 0xA7, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xC3, 0xA6, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00
992
993
994

// roundtrip
json j_from_msgpack = json::from_msgpack(v_msgpack);
Niels Lohmann's avatar
Niels Lohmann committed
995
996
997
998
999
1000

// 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