diff --git a/.gitignore b/.gitignore index 3bca6b87..2c6c1e15 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,8 @@ cmake-build-debug test/test-* /.vs + +doc/mkdocs/venv/ +doc/mkdocs/docs/images +doc/mkdocs/docs/examples +doc/mkdocs/site diff --git a/doc/Doxyfile b/doc/Doxyfile index 2c44d006..eacefb45 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -110,9 +110,7 @@ WARN_LOGFILE = # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ../single_include/nlohmann/json.hpp \ - index.md \ - faq.md \ - binary_formats.md + index.md INPUT_ENCODING = UTF-8 FILE_PATTERNS = RECURSIVE = NO diff --git a/doc/binary_formats.md b/doc/binary_formats.md deleted file mode 100644 index b9f233ca..00000000 --- a/doc/binary_formats.md +++ /dev/null @@ -1,171 +0,0 @@ -# Binary formats - -![conversion between JSON and binary formats](images/binary.png) - -Several formats exist that encode JSON values in a binary format to reduce the size of the encoded value as well as the required effort to parse encoded value. The library implements three formats, namely - -- [CBOR](https://tools.ietf.org/html/rfc7049) (Concise Binary Object Representation) -- [MessagePack](https://msgpack.org) -- [UBJSON](http://ubjson.org) (Universal Binary JSON) - -## Interface - -### JSON to binary format - -For each format, the `to_*` functions (i.e., `to_cbor`, `to_msgpack`, and `to_ubjson`) convert a JSON value into the respective binary format. Taking CBOR as example, the concrete prototypes are: - -```cpp -static std::vector to_cbor(const basic_json& j); // 1 -static void to_cbor(const basic_json& j, detail::output_adapter o); // 2 -static void to_cbor(const basic_json& j, detail::output_adapter o); // 3 -``` - -The first function creates a byte vector from the given JSON value. The second and third function writes to an output adapter of `uint8_t` and `char`, respectively. Output adapters are implemented for strings, output streams, and vectors. - -Given a JSON value `j`, the following calls are possible: - -```cpp -std::vector v; -v = json::to_cbor(j); // 1 - -json::to_cbor(j, v); // 2 - -std::string s; -json::to_cbor(j, s); // 3 - -std::ostringstream oss; -json::to_cbor(j, oss); // 3 -``` - -### Binary format to JSON - -Likewise, the `from_*` functions (i.e, `from_cbor`, `from_msgpack`, and `from_ubjson`) convert a binary encoded value into a JSON value. Taking CBOR as example, the concrete prototypes are: - -```cpp -static basic_json from_cbor(detail::input_adapter i, const bool strict = true); // 1 -static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true); // 2 -``` - -Both functions read from an input adapter: the first function takes it directly form argument `i`, whereas the second function creates it from the provided arguments `a1` and `a2`. If the optional parameter `strict` is true, the input must be read completely (or a parse error exception is thrown). If it is false, parsing succeeds even if the input is not completely read. - -Input adapters are implemented for input streams, character buffers, string literals, and iterator ranges. - -Given several inputs (which we assume to be filled with a CBOR value), the following calls are possible: - -```cpp -std::string s; -json j1 = json::from_cbor(s); // 1 - -std::ifstream is("somefile.cbor", std::ios::binary); -json j2 = json::from_cbor(is); // 1 - -std::vector v; -json j3 = json::from_cbor(v); // 1 - -const char* buff; -std::size_t buff_size; -json j4 = json::from_cbor(buff, buff_size); // 2 -``` - -## Details - -### CBOR - -The mapping from CBOR to JSON is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors (parse_error.112): - -- byte strings (0x40..0x5F) -- date/time (0xC0..0xC1) -- bignum (0xC2..0xC3) -- decimal fraction (0xC4) -- bigfloat (0xC5) -- tagged items (0xC6..0xD4, 0xD8..0xDB) -- expected conversions (0xD5..0xD7) -- simple values (0xE0..0xF3, 0xF8) -- undefined (0xF7) - -CBOR further allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected (parse_error.113). - -The mapping from JSON to CBOR is **complete** in the sense that any JSON value type can be converted to a CBOR value. - -If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the dump() function which serializes NaN or Infinity to null. - -The following CBOR types are not used in the conversion: - -- byte strings (0x40..0x5F) -- UTF-8 strings terminated by "break" (0x7F) -- arrays terminated by "break" (0x9F) -- maps terminated by "break" (0xBF) -- date/time (0xC0..0xC1) -- bignum (0xC2..0xC3) -- decimal fraction (0xC4) -- bigfloat (0xC5) -- tagged items (0xC6..0xD4, 0xD8..0xDB) -- expected conversions (0xD5..0xD7) -- simple values (0xE0..0xF3, 0xF8) -- undefined (0xF7) -- half and single-precision floats (0xF9-0xFA) -- break (0xFF) - -### MessagePack - -The mapping from MessagePack to JSON is **incomplete** in the sense that not all MessagePack types can be converted to a JSON value. The following MessagePack types are not supported and will yield parse errors: - -- bin 8 - bin 32 (0xC4..0xC6) -- ext 8 - ext 32 (0xC7..0xC9) -- fixext 1 - fixext 16 (0xD4..0xD8) - -The mapping from JSON to MessagePack is **complete** in the sense that any JSON value type can be converted to a MessagePack value. - -The following values can not be converted to a MessagePack value: - -- strings with more than 4294967295 bytes -- arrays with more than 4294967295 elements -- objects with more than 4294967295 elements - -The following MessagePack types are not used in the conversion: - -- bin 8 - bin 32 (0xC4..0xC6) -- ext 8 - ext 32 (0xC7..0xC9) -- float 32 (0xCA) -- fixext 1 - fixext 16 (0xD4..0xD8) - -Any MessagePack output created `to_msgpack` can be successfully parsed by `from_msgpack`. - -If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the `dump()` function which serializes NaN or Infinity to `null`. - -### UBJSON - -The mapping from UBJSON to JSON is **complete** in the sense that any UBJSON value can be converted to a JSON value. - -The mapping from JSON to UBJSON is **complete** in the sense that any JSON value type can be converted to a UBJSON value. - -The following values can not be converted to a UBJSON value: - -- strings with more than 9223372036854775807 bytes (theoretical) -- unsigned integer numbers above 9223372036854775807 - -The following markers are not used in the conversion: - -- `Z`: no-op values are not created. -- `C`: single-byte strings are serialized with S markers. - -Any UBJSON output created to_ubjson can be successfully parsed by from_ubjson. - -If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the `dump()` function which serializes NaN or Infinity to null. - -The optimized formats for containers are supported: Parameter `use_size` adds size information to the beginning of a container and removes the closing marker. Parameter `use_type` further checks whether all elements of a container have the same type and adds the type marker to the beginning of the container. The `use_type` parameter must only be used together with `use_size = true`. Note that `use_size = true` alone may result in larger representations - the benefit of this parameter is that the receiving side is immediately informed on the number of elements of the container. - -## Size comparison examples - -The following table shows the size compared to the original JSON value for different files from the repository for the different formats. - -| format | sample.json | all_unicode.json | floats.json | signed_ints.json | jeopardy.json | canada.json | -| ----------------------- | -----------:| ----------------:| -----------:| ----------------:| -------------:| -----------:| -| JSON | 100.00 % | 100.00 % | 100.00 % | 100.00 % | 100.00 % | 100.00 % | -| CBOR | 87.21 % | 71.18 % | 48.20 % | 44.16 % | 87.96 % | 50.53 % | -| MessagePack | 87.16 % | 71.18 % | 48.20 % | 44.16 % | 87.91 % | 50.56 % | -| UBJSON unoptimized | 88.15 % | 100.00 % | 48.20 % | 44.16 % | 96.58 % | 53.20 % | -| UBJSON size-optimized | 89.26 % | 100.00 % | 48.20 % | 44.16 % | 97.40 % | 58.56 % | -| UBJSON format-optimized | 89.45 % | 100.00 % | 42.85 % | 39.26 % | 94.96 % | 55.93 % | - -The results show that there does not exist a "best" encoding. Furthermore, it is not always worthwhile to use UBJSON's optimizations. diff --git a/doc/faq.md b/doc/faq.md deleted file mode 100644 index 14125ee3..00000000 --- a/doc/faq.md +++ /dev/null @@ -1,87 +0,0 @@ -# FAQ - -## Parsing - -### How can I parse from a string? - -```cpp -json j = json::parse("[1,2,3,4]"); -``` - -You can pass string literals (as above), `std::string`, `const char*` or byte containers such as `std::vector`. - -### How can I parse from a file? - -```cpp -std::ifstream i("your_file.json"); -json j = json::parse(i); -``` - -## Serialization - -### How can I serialize a JSON value - -```cpp -std::cout << j << std::endl; -``` - -This is equivalent to - -```cpp -std::string s = j.dump(); -std::cout << s << std::endl; -``` - -### How can I pretty-print a JSON value - -```cpp -std::cout << std::setw(4) << j << std::endl; -``` - -This is equivalent to - -```cpp -std::string s = j.dump(4); -std::cout << s << std::endl; -``` - -The number `4` denotes the number of spaces used for indentation. - -## Iterating - -### How can I iterate over a JSON value? - -```cpp -for (json& val : j) -{ - // val is a reference for the current value -} -``` - -This works with any JSON value, also primitive values like numbers. - -### How can I access the keys when iterating over a JSON object? - -```cpp -for (auto it = j.begin(); it != j.end(); ++it) -{ - // the value - json &val = it.value(); - - // the key (for objects) - const std::string &key = it.key(); -} -``` - -You can also use an iteration wrapper and use range for: - -```cpp -for (auto it : json::iteration_wrapper(j)) -{ - // the value - json &val = it.value(); - - // the key (for objects) - const std::string &key = it.key(); -} -``` diff --git a/doc/images/binary.png b/doc/images/binary.png deleted file mode 100644 index 2579fd8f..00000000 Binary files a/doc/images/binary.png and /dev/null differ diff --git a/doc/mkdocs/Makefile b/doc/mkdocs/Makefile new file mode 100644 index 00000000..bb97420a --- /dev/null +++ b/doc/mkdocs/Makefile @@ -0,0 +1,31 @@ +# serve the site locally +serve: prepare_files + venv/bin/mkdocs serve + +# create files that are not versioned inside the mkdocs folder +prepare_files: clean + # build Doxygen + $(MAKE) -C .. + # create subfolders + mkdir docs/images docs/examples + # copy images + cp -vr ../json.gif ../images/range-begin-end.svg ../images/range-rbegin-rend.svg docs/images + # copy examples + cp -vr ../examples/*.cpp ../examples/*.output docs/examples + +# clean subfolders +clean: + rm -fr docs/images docs/examples + +# publish site to GitHub pages +publish: prepare_files + venv/bin/mkdocs gh-deploy --clean --force + +# install a Python virtual environment +install_venv: requirements.txt + python3 -mvenv venv + venv/bin/pip install -r requirements.txt + +# uninstall the virtual environment +uninstall_venv: clean + rm -fr venv diff --git a/doc/mkdocs/docs/features/arbitrary_types.md b/doc/mkdocs/docs/features/arbitrary_types.md new file mode 100644 index 00000000..3d238317 --- /dev/null +++ b/doc/mkdocs/docs/features/arbitrary_types.md @@ -0,0 +1,223 @@ +# Arbitrary Types Conversions + +Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines: + +```cpp +namespace ns { + // a simple struct to model a person + struct person { + std::string name; + std::string address; + int age; + }; +} + +ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// convert to JSON: copy each value into the JSON object +json j; +j["name"] = p.name; +j["address"] = p.address; +j["age"] = p.age; + +// ... + +// convert from JSON: copy each value from the JSON object +ns::person p { + j["name"].get(), + j["address"].get(), + j["age"].get() +}; +``` + +It works, but that's quite a lot of boilerplate... Fortunately, there's a better way: + +```cpp +// create a person +ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// conversion: person -> json +json j = p; + +std::cout << j << std::endl; +// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} + +// conversion: json -> person +auto p2 = j.get(); + +// that's it +assert(p == p2); +``` + +## Basic usage + +To make this work with one of your types, you only need to provide two functions: + +```cpp +using nlohmann::json; + +namespace ns { + void to_json(json& j, const person& p) { + j = json{ {"name", p.name}, {"address", p.address}, {"age", p.age} }; + } + + void from_json(const json& j, person& p) { + j.at("name").get_to(p.name); + j.at("address").get_to(p.address); + j.at("age").get_to(p.age); + } +} // namespace ns +``` + +That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. +Likewise, when calling `get()` or `get_to(your_type&)`, the `from_json` method will be called. + +Some important things: + +* 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). +* 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. +* When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) +* 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. +* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. + + +## How do I convert third-party types? + +This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: + +The library uses **JSON Serializers** to convert types to json. +The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)). + +It is implemented like this (simplified): + +```cpp +template +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 + } +}; +``` + +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`... + +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 { + template + struct adl_serializer> { + static void to_json(json& j, const boost::optional& opt) { + if (opt == boost::none) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! + } + } + + static void from_json(const json& j, boost::optional& opt) { + if (j.is_null()) { + opt = boost::none; + } else { + opt = j.get(); // same as above, but with + // adl_serializer::from_json + } + } + }; +} +``` + +## How can I use `get()` for non-default constructible/non-copyable types? + +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: + +```cpp +struct move_only_type { + 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; + + int i; +}; + +namespace nlohmann { + template <> + struct adl_serializer { + // note: the return type is no longer 'void', and the method only takes + // one argument + static move_only_type from_json(const json& j) { + return {j.get()}; + } + + // 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 + static void to_json(json& j, move_only_type t) { + j = t.i; + } + }; +} +``` + +## Can I write my own serializer? (Advanced use) + +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. + +If you write your own serializer, you'll need to do a few things: + +- 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 + +Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL. + +```cpp +// You should use void as a second template argument +// if you don't need compile-time checks on T +template::type> +struct less_than_32_serializer { + template + 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); + } + + template + static void from_json(const BasicJsonType& j, T& value) { + // same thing here + using nlohmann::from_json; + from_json(j, value); + } +}; +``` + +Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention: + +```cpp +template +struct bad_serializer +{ + template + static void to_json(BasicJsonType& j, const T& value) { + // this calls BasicJsonType::json_serializer::to_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + j = value; + } + + template + static void to_json(const BasicJsonType& j, T& value) { + // this calls BasicJsonType::json_serializer::from_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + value = j.template get(); // oops! + } +}; +``` diff --git a/doc/mkdocs/docs/features/binary_formats/bson.md b/doc/mkdocs/docs/features/binary_formats/bson.md new file mode 100644 index 00000000..0ed2a786 --- /dev/null +++ b/doc/mkdocs/docs/features/binary_formats/bson.md @@ -0,0 +1,94 @@ +# BSON + +BSON, short for Bin­ary JSON, is a bin­ary-en­coded seri­al­iz­a­tion of JSON-like doc­u­ments. Like JSON, BSON sup­ports the em­bed­ding of doc­u­ments and ar­rays with­in oth­er doc­u­ments and ar­rays. BSON also con­tains ex­ten­sions that al­low rep­res­ent­a­tion of data types that are not part of the JSON spec. For ex­ample, BSON has a Date type and a BinData type. + +!!! abstract "References" + + - [BSON Website](http://bsonspec.org) - the main source on BSON + - [BSON Specification](http://bsonspec.org/spec.html) - the specification + + +## Serialization + +The library uses the following mapping from JSON values types to BSON types: + +JSON value type | value/range | BSON type | marker +--------------- | --------------------------------- | ----------- | ------ +null | `null` | null | 0x0A +boolean | `true`, `false` | boolean | 0x08 +number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 +number_integer | -2147483648..2147483647 | int32 | 0x10 +number_integer | 2147483648..9223372036854775807 | int64 | 0x12 +number_unsigned | 0..2147483647 | int32 | 0x10 +number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 +number_unsigned | 9223372036854775808..18446744073709551615| -- | -- +number_float | *any value* | double | 0x01 +string | *any value* | string | 0x02 +array | *any value* | document | 0x04 +object | *any value* | document | 0x03 +binary | *any value* | binary | 0x05 + +!!! warning "Incomplete mapping" + + The mapping is **incomplete**, since only JSON-objects (and things + contained therein) can be serialized to BSON. + Also, integers larger than 9223372036854775807 cannot be serialized to BSON, + and the keys may not contain U+0000, since they are serialized a + zero-terminated c-strings. + +??? example + + ```cpp + --8<-- "examples/to_bson.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_bson.output" + ``` + + +## Deserialization + +The library maps BSON record types to JSON value types as follows: + +BSON type | BSON marker byte | JSON value type +--------------- | ---------------- | --------------------------- +double | 0x01 | number_float +string | 0x02 | string +document | 0x03 | object +array | 0x04 | array +binary | 0x05 | binary +undefined | 0x06 | *unsupported* +ObjectId | 0x07 | *unsupported* +boolean | 0x08 | boolean +UTC Date-Time | 0x09 | *unsupported* +null | 0x0A | null +Regular Expr. | 0x0B | *unsupported* +DB Pointer | 0x0C | *unsupported* +JavaScript Code | 0x0D | *unsupported* +Symbol | 0x0E | *unsupported* +JavaScript Code | 0x0F | *unsupported* +int32 | 0x10 | number_integer +Timestamp | 0x11 | *unsupported* +128-bit decimal float | 0x13 | *unsupported* +Max Key | 0x7F | *unsupported* +Min Key | 0xFF | *unsupported* + +!!! warning "Incomplete mapping" + + The mapping is **incomplete**. The unsupported mappings are indicated in the table above. + + +??? example + + ```cpp + --8<-- "examples/from_bson.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bson.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_formats/cbor.md b/doc/mkdocs/docs/features/binary_formats/cbor.md new file mode 100644 index 00000000..daea3a51 --- /dev/null +++ b/doc/mkdocs/docs/features/binary_formats/cbor.md @@ -0,0 +1,172 @@ +# CBOR + +The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small code size, fairly small message size, and extensibility without the need for version negotiation. + +!!! abstract "References" + + - [CBOR Website](http://cbor.io) - the main source on CBOR + - [CBOR Playground](http://cbor.me) - an interactive webpage to translate between JSON and CBOR + - [RFC 7049](https://tools.ietf.org/html/rfc7049) - the CBOR specification + +## Serialization + +The library uses the following mapping from JSON values types to CBOR types according to the CBOR specification (RFC 7049): + +JSON value type | value/range | CBOR type | first byte +--------------- | ------------------------------------------ | ---------------------------------- | --------------- +null | `null` | Null | 0xF6 +boolean | `true` | True | 0xF5 +boolean | `false` | False | 0xF4 +number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B +number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A +number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 +number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 +number_integer | -24..-1 | Negative integer | 0x20..0x37 +number_integer | 0..23 | Integer | 0x00..0x17 +number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 +number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 +number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A +number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B +number_unsigned | 0..23 | Integer | 0x00..0x17 +number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 +number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 +number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A +number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B +number_float | *any value representable by a float* | Single-Precision Float | 0xFA +number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB +string | *length*: 0..23 | UTF-8 string | 0x60..0x77 +string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 +string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 +string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A +string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B +array | *size*: 0..23 | array | 0x80..0x97 +array | *size*: 23..255 | array (1 byte follow) | 0x98 +array | *size*: 256..65535 | array (2 bytes follow) | 0x99 +array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A +array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B +object | *size*: 0..23 | map | 0xA0..0xB7 +object | *size*: 23..255 | map (1 byte follow) | 0xB8 +object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 +object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA +object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB +binary | *size*: 0..23 | byte string | 0x40..0x57 +binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 +binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 +binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A +binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B + + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any JSON value type can be converted to a CBOR value. + +!!! info "NaN/infinity handling" + + If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`. + + +!!! info "Unused CBOR types" + + The following CBOR types are not used in the conversion: + + - UTF-8 strings terminated by "break" (0x7F) + - arrays terminated by "break" (0x9F) + - maps terminated by "break" (0xBF) + - byte strings terminated by "break" (0x5F) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + - half-precision floats (0xF9) + - break (0xFF) + +??? example + + ```cpp + --8<-- "examples/to_cbor.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_cbor.output" + ``` + +## Deserialization + +The library maps CBOR types to JSON value types as follows: + +CBOR type | JSON value type | first byte +---------------------- | --------------- | ---------- +Integer | number_unsigned | 0x00..0x17 +Unsigned integer | number_unsigned | 0x18 +Unsigned integer | number_unsigned | 0x19 +Unsigned integer | number_unsigned | 0x1A +Unsigned integer | number_unsigned | 0x1B +Negative integer | number_integer | 0x20..0x37 +Negative integer | number_integer | 0x38 +Negative integer | number_integer | 0x39 +Negative integer | number_integer | 0x3A +Negative integer | number_integer | 0x3B +Byte string | binary | 0x40..0x57 +Byte string | binary | 0x58 +Byte string | binary | 0x59 +Byte string | binary | 0x5A +Byte string | binary | 0x5B +UTF-8 string | string | 0x60..0x77 +UTF-8 string | string | 0x78 +UTF-8 string | string | 0x79 +UTF-8 string | string | 0x7A +UTF-8 string | string | 0x7B +UTF-8 string | string | 0x7F +array | array | 0x80..0x97 +array | array | 0x98 +array | array | 0x99 +array | array | 0x9A +array | array | 0x9B +array | array | 0x9F +map | object | 0xA0..0xB7 +map | object | 0xB8 +map | object | 0xB9 +map | object | 0xBA +map | object | 0xBB +map | object | 0xBF +False | `false` | 0xF4 +True | `true` | 0xF5 +Null | `null` | 0xF6 +Half-Precision Float | number_float | 0xF9 +Single-Precision Float | number_float | 0xFA +Double-Precision Float | number_float | 0xFB + +!!! warning "Incomplete mapping" + + The mapping is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors: + + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - tagged items (0xC6..0xD4, 0xD8..0xDB) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + +!!! warning "Object keys" + + CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected. + +??? example + + ```cpp + --8<-- "examples/from_cbor.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_cbor.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_formats/index.md b/doc/mkdocs/docs/features/binary_formats/index.md new file mode 100644 index 00000000..55f963c2 --- /dev/null +++ b/doc/mkdocs/docs/features/binary_formats/index.md @@ -0,0 +1,45 @@ +# Overview + +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](bson.md) (Binary JSON), +- [CBOR](cbor.md) (Concise Binary Object Representation), +- [MessagePack](messagepack.md), and +- [UBJSON](ubjson.md) (Universal Binary JSON) + +to efficiently encode JSON values to byte vectors and to decode such vectors. + +## Comparison + +### Completeness + +| Format | Serialization | Deserialization | +| ----------- |---------------------------------------------- | -------------------------------------------- | +| BSON | incomplete: top-level value must be an object | incomplete, but all JSON types are supported | +| CBOR | complete | incomplete, but all JSON types are supported | +| MessagePack | complete | complete | +| UBJSON | complete | complete | + +### Binary values + +| Format | Binary values | Binary subtypes | +| ----------- | ------------- | --------------- | +| BSON | supported | supported | +| CBOR | supported | not supported | +| MessagePack | supported | supported | +| UBJSON | not supported | not supported | + +See [binary values](../binary_values.md) for more information. + +### Sizes + +| Format | canada.json | twitter.json | citm_catalog.json | jeopardy.json | +| ------------------ | ----------- | ------------ | ----------------- | ------------- | +| BSON | 85,8 % | 95,2 % | 95,8 % | 106,7 % | +| CBOR | 50,5 % | 86,3 % | 68,4 % | 88,0 % | +| MessagePack | 50,6 % | 86,0 % | 68,5 % | 87,9 % | +| UBJSON | 53,2 % | 91,3 % | 78,2 % | 96,6 % | +| UBJSON (size) | 58,6 % | 92,3 % | 86,8 % | 97,4 % | +| UBJSON (size+type) | 55,9 % | 92,3 % | 85,0 % | 95,0 % | + +Sizes compared to minified JSON value. diff --git a/doc/mkdocs/docs/features/binary_formats/messagepack.md b/doc/mkdocs/docs/features/binary_formats/messagepack.md new file mode 100644 index 00000000..ed061056 --- /dev/null +++ b/doc/mkdocs/docs/features/binary_formats/messagepack.md @@ -0,0 +1,142 @@ +# MessagePack + +MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it's faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves. + +!!! abstract "References" + + - [MessagePack website](https://msgpack.org) + - [MessagePack specification](https://github.com/msgpack/msgpack/blob/master/spec.md) + +## Serialization + +The library uses the following mapping from JSON values types to MessagePack types according to the MessagePack specification: + +JSON value type | value/range | MessagePack type | first byte +--------------- | --------------------------------- | ---------------- | ---------- +null | `null` | nil | 0xC0 +boolean | `true` | true | 0xC3 +boolean | `false` | false | 0xC2 +number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 +number_integer | -2147483648..-32769 | int32 | 0xD2 +number_integer | -32768..-129 | int16 | 0xD1 +number_integer | -128..-33 | int8 | 0xD0 +number_integer | -32..-1 | negative fixint | 0xE0..0xFF +number_integer | 0..127 | positive fixint | 0x00..0x7F +number_integer | 128..255 | uint 8 | 0xCC +number_integer | 256..65535 | uint 16 | 0xCD +number_integer | 65536..4294967295 | uint 32 | 0xCE +number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF +number_unsigned | 0..127 | positive fixint | 0x00..0x7F +number_unsigned | 128..255 | uint 8 | 0xCC +number_unsigned | 256..65535 | uint 16 | 0xCD +number_unsigned | 65536..4294967295 | uint 32 | 0xCE +number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF +number_float | *any value* | float 64 | 0xCB +string | *length*: 0..31 | fixstr | 0xA0..0xBF +string | *length*: 32..255 | str 8 | 0xD9 +string | *length*: 256..65535 | str 16 | 0xDA +string | *length*: 65536..4294967295 | str 32 | 0xDB +array | *size*: 0..15 | fixarray | 0x90..0x9F +array | *size*: 16..65535 | array 16 | 0xDC +array | *size*: 65536..4294967295 | array 32 | 0xDD +object | *size*: 0..15 | fix map | 0x80..0x8F +object | *size*: 16..65535 | map 16 | 0xDE +object | *size*: 65536..4294967295 | map 32 | 0xDF +binary | *size*: 0..255 | bin 8 | 0xC4 +binary | *size*: 256..65535 | bin 16 | 0xC5 +binary | *size*: 65536..4294967295 | bin 32 | 0xC6 + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any JSON value type can be converted to a MessagePack value. + + Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`. + +!!! warning "Size constraints" + + The following values can **not** be converted to a MessagePack value: + + - strings with more than 4294967295 bytes + - byte strings with more than 4294967295 bytes + - arrays with more than 4294967295 elements + - objects with more than 4294967295 elements + +!!! info "Unused MessagePack types" + + The following MessagePack types are not used in the conversion: float 32 (0xCA) + +!!! info "NaN/infinity handling" + + If NaN or Infinity are stored inside a JSON number, they are serialized properly. function which serializes NaN or Infinity to `null`. + +??? example + + ```cpp + --8<-- "examples/to_msgpack.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_msgpack.output" + ``` + +## Deserialization + +The library maps MessagePack types to JSON value types as follows: + +MessagePack type | JSON value type | first byte +---------------- | --------------- | ---------- +positive fixint | number_unsigned | 0x00..0x7F +fixmap | object | 0x80..0x8F +fixarray | array | 0x90..0x9F +fixstr | string | 0xA0..0xBF +nil | `null` | 0xC0 +false | `false` | 0xC2 +true | `true` | 0xC3 +float 32 | number_float | 0xCA +float 64 | number_float | 0xCB +uint 8 | number_unsigned | 0xCC +uint 16 | number_unsigned | 0xCD +uint 32 | number_unsigned | 0xCE +uint 64 | number_unsigned | 0xCF +int 8 | number_integer | 0xD0 +int 16 | number_integer | 0xD1 +int 32 | number_integer | 0xD2 +int 64 | number_integer | 0xD3 +str 8 | string | 0xD9 +str 16 | string | 0xDA +str 32 | string | 0xDB +array 16 | array | 0xDC +array 32 | array | 0xDD +map 16 | object | 0xDE +map 32 | object | 0xDF +bin 8 | binary | 0xC4 +bin 16 | binary | 0xC5 +bin 32 | binary | 0xC6 +ext 8 | binary | 0xC7 +ext 16 | binary | 0xC8 +ext 32 | binary | 0xC9 +fixext 1 | binary | 0xD4 +fixext 2 | binary | 0xD5 +fixext 4 | binary | 0xD6 +fixext 8 | binary | 0xD7 +fixext 16 | binary | 0xD8 +negative fixint | number_integer | 0xE0-0xFF + +!!! info + + Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`. + + +??? example + + ```cpp + --8<-- "examples/from_msgpack.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_msgpack.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_formats/ubjson.md b/doc/mkdocs/docs/features/binary_formats/ubjson.md new file mode 100644 index 00000000..cb01cfde --- /dev/null +++ b/doc/mkdocs/docs/features/binary_formats/ubjson.md @@ -0,0 +1,133 @@ +# UBJSON + +Universal Binary JSON (UBJSON) is a binary form directly imitating JSON, but requiring fewer bytes of data. It aims to achieve the generality of JSON, combined with being much easier to process than JSON. + +!!! abstract "References" + + - [UBJSON Website](http://ubjson.org) + +## Serialization + +The library uses the following mapping from JSON values types to UBJSON types according to the UBJSON specification: + +JSON value type | value/range | UBJSON type | marker +--------------- | --------------------------------- | ----------- | ------ +null | `null` | null | `Z` +boolean | `true` | true | `T` +boolean | `false` | false | `F` +number_integer | -9223372036854775808..-2147483649 | int64 | `L` +number_integer | -2147483648..-32769 | int32 | `l` +number_integer | -32768..-129 | int16 | `I` +number_integer | -128..127 | int8 | `i` +number_integer | 128..255 | uint8 | `U` +number_integer | 256..32767 | int16 | `I` +number_integer | 32768..2147483647 | int32 | `l` +number_integer | 2147483648..9223372036854775807 | int64 | `L` +number_unsigned | 0..127 | int8 | `i` +number_unsigned | 128..255 | uint8 | `U` +number_unsigned | 256..32767 | int16 | `I` +number_unsigned | 32768..2147483647 | int32 | `l` +number_unsigned | 2147483648..9223372036854775807 | int64 | `L` +number_float | *any value* | float64 | `D` +string | *with shortest length indicator* | string | `S` +array | *see notes on optimized format* | array | `[` +object | *see notes on optimized format* | map | `{` + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any JSON value type can be converted to a UBJSON value. + + Any UBJSON output created by `to_ubjson` can be successfully parsed by `from_ubjson`. + +!!! warning "Size constraints" + + The following values can **not** be converted to a UBJSON value: + + - strings with more than 9223372036854775807 bytes (theoretical) + - unsigned integer numbers above 9223372036854775807 + +!!! info "Unused UBJSON markers" + + The following markers are not used in the conversion: + + - `Z`: no-op values are not created. + - `C`: single-byte strings are serialized with `S` markers. + +!!! info "NaN/infinity handling" + + If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the `dump()` + function which serializes NaN or Infinity to `null`. + +!!! info "Optimized formats" + + The optimized formats for containers are supported: Parameter + `use_size` adds size information to the beginning of a container and + removes the closing marker. Parameter `use_type` further checks + whether all elements of a container have the same type and adds the + type marker to the beginning of the container. The `use_type` + parameter must only be used together with `use_size = true`. + + Note that `use_size = true` alone may result in larger representations - + the benefit of this parameter is that the receiving side is + immediately informed on the number of elements of the container. + +!!! info "Binary values" + + If the JSON data contains the binary type, the value stored is a list + of integers, as suggested by the UBJSON documentation. In particular, + this means that serialization and the deserialization of a JSON + containing binary values into UBJSON and back will result in a + different JSON object. + + +??? example + + ```cpp + --8<-- "examples/to_ubjson.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_ubjson.output" + ``` + +## Deserialization + +The library maps UBJSON types to JSON value types as follows: + +UBJSON type | JSON value type | marker +----------- | --------------------------------------- | ------ +no-op | *no value, next value is read* | `N` +null | `null` | `Z` +false | `false` | `F` +true | `true` | `T` +float32 | number_float | `d` +float64 | number_float | `D` +uint8 | number_unsigned | `U` +int8 | number_integer | `i` +int16 | number_integer | `I` +int32 | number_integer | `l` +int64 | number_integer | `L` +string | string | `S` +char | string | `C` +array | array (optimized values are supported) | `[` +object | object (optimized values are supported) | `{` + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any UBJSON value can be converted to a JSON value. + + +??? example + + ```cpp + --8<-- "examples/from_ubjson.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_ubjson.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_values.md b/doc/mkdocs/docs/features/binary_values.md new file mode 100644 index 00000000..e268a5b5 --- /dev/null +++ b/doc/mkdocs/docs/features/binary_values.md @@ -0,0 +1,294 @@ +# Binary Values + +The library implements several [binary formats](binary_formats/index.md) that encode JSON in an efficient way. Most of these formats support binary values; that is, values that have semantics define outside the library and only define a sequence of bytes to be stored. + +JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store values received by a binary format. Binary values are never created by the JSON parser, and are only part of a serialized JSON text if they have been created manually or via a binary format. + +## API for binary values + +```plantuml +class json::binary_t { + -- setters -- + +void set_subtype(std::uint8_t subtype) + +void clear_subtype() + -- getters -- + +std::uint8_t subtype() const + +bool has_subtype() const +} + +"std::vector" <|-- json::binary_t +``` + +By default, binary values are stored as `std::vector`. This type can be changed by providing a template parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as `json::binary_t`: + +```cpp +auto binary = json::binary_t({0xCA, 0xFE, 0xBA, 0xBE}); +auto binary_with_subtype = json::binary_t({0xCA, 0xFE, 0xBA, 0xBE}, 42); +``` + +There are several convenience functions to check and set the subtype: + +```cpp +binary.has_subtype(); // returns false +binary_with_subtype.has_subtype(); // returns true + +binary_with_subtype.clear_subtype(); +binary_with_subtype.has_subtype(); // returns true + +binary_with_subtype.set_subtype(42); +binary.set_subtype(23); + +binary.subtype(); // returns 23 +``` + +As `json::binary_t` is subclassing `std::vector`, all member functions are available: + +```cpp +binary.size(); // returns 4 +binary[1]; // returns 0xFE +``` + +JSON values can be constructed from `json::binary_t`: + +```cpp +json j = binary; +``` + +Binary values are primitive values just like numbers or strings: + +```cpp +j.is_binary(); // returns true +j.is_primitive(); // returns true +``` + +Given a binary JSON value, the `binary_t` can be accessed by reference as via `get_binary()`: + +```cpp +j.get_binary().has_subtype(); // returns true +j.get_binary().size(); // returns 4 +``` + +For convencience, binary JSON values can be constructed via `json::binary`: + +```cpp +auto j2 = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 23); +auto j3 = json::binary({0xCA, 0xFE, 0xBA, 0xBE}); + +j2 == j; // returns true +j3.get_binary().has_subtype(); // returns false +``` + + + +## Serialization + +Binary values are serialized differently according to the formats. + +### JSON + +JSON does not have a binary type, and this library does not introduce a new type as this would break conformance. Instead, binary values are serialized as an object with two keys: `bytes` holds an array of integers, and `subtype` is an integer or `null`. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // serialize to standard output + std::cout << j.dump(2) << std::endl; + ``` + + Output: + + ```json + { + "binary": { + "bytes": [202, 254, 186, 190], + "subtype": 42 + } + } + ``` + +!!! warning "No roundtrip for binary values" + + The JSON parser will not parse the objects generated by binary values back to binary values. This is by design to remain standards compliant. Serializing binary values to JSON is only implemented for debugging purposes. + +### BSON + +[BSON](binary_formats/bson.md) supports binary values and subtypes. If a subtype is given, it is used and added as unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 is used. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to BSON + auto v = json::to_bson(j); + ``` + + `v` is a `std::vector` with the following 22 elements: + + ```c + 0x16 0x00 0x00 0x00 // number of bytes in the document + 0x05 // binary value + 0x62 0x69 0x6E 0x61 0x72 0x79 0x00 // key "binary" + null byte + 0x04 0x00 0x00 0x00 // number of bytes + 0x2a // subtype + 0xCA 0xFE 0xBA 0xBE // content + 0x00 // end of the document + ``` + + Note that the serialization preserves the subtype, and deserializing `v` would yield the following value: + + ```json + { + "binary": { + "bytes": [202, 254, 186, 190], + "subtype": 42 + } + } + ``` + +### CBOR + +[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Any binary value will be serialized as byte strings. The library will choose the smallest representation using the length of the byte array. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 (will be ignored by CBOR) + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to CBOR + auto v = json::to_cbor(j); + ``` + + `v` is a `std::vector` with the following 13 elements: + + ```c + 0xA1 // map(1) + 0x66 // text(6) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x44 // bytes(4) + 0xCA 0xFE 0xBA 0xBE // content + ``` + + Note the subtype (42) is **not** serialized, and deserializing `v` would yield the following value: + + ```json + { + "binary": { + "bytes": [202, 254, 186, 190], + "subtype": null + } + } + ``` + +### MessagePack + +[MessagePack](binary_formats/messagepack.md) supports binary values and subtypes. If a subtype is given, the ext family is used. The library will choose the smallest representation among fixext1, fixext2, fixext4, fixext8, ext8, ext16, and ext32. The subtype is then added as singed 8-bit integer. + +If no subtype is given, the bin family (bin8, bin16, bin32) is used. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to MessagePack + auto v = json::to_msgpack(j); + ``` + + `v` is a `std::vector` with the following 14 elements: + + ```c + 0x81 // fixmap1 + 0xA6 // fixstr6 + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0xD6 // fixext4 + 0x2A // subtype + 0xCA 0xFE 0xBA 0xBE // content + ``` + + Note that the serialization preserves the subtype, and deserializing `v` would yield the following value: + + ```json + { + "binary": { + "bytes": [202, 254, 186, 190], + "subtype": 42 + } + } + ``` + +### UBJSON + +[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values as array of uint8 values. This translation is implemented by the library. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 (will be ignored in UBJSON) + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to UBJSON + auto v = json::to_msgpack(j); + ``` + + `v` is a `std::vector` with the following 20 elements: + + ```c + 0x7B // '{' + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x5B // '[' + 0x55 0xCA 0x55 0xFE 0x55 0xBA 0x55 0xBE // content (each byte prefixed with 'U') + 0x5D // ']' + 0x7D // '}' + ``` + + The following code uses the type and size optimization for UBJSON: + + ```cpp + // convert to UBJSON using the size and type optimization + auto v = json::to_ubjson(j, true, true); + ``` + + The resulting vector has 23 elements; the optimization is not effective for examples with few values: + + ```c + 0x7B // '{' + 0x24 // '$' type of the object elements + 0x5B // '[' array + 0x23 0x69 0x01 // '#' i 1 number of object elements + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x24 0x55 // '$' 'U' type of the array elements: unsinged integers + 0x23 0x69 0x04 // '#' i 4 number of array elements + 0xCA 0xFE 0xBA 0xBE // content + ``` + + Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would yield the following value: + + ```json + { + "binary": [202, 254, 186, 190] + } + ``` diff --git a/doc/mkdocs/docs/features/enum_conversion.md b/doc/mkdocs/docs/features/enum_conversion.md new file mode 100644 index 00000000..1c1bb803 --- /dev/null +++ b/doc/mkdocs/docs/features/enum_conversion.md @@ -0,0 +1,53 @@ +# 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 serialization 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() == TS_RUNNING); + +// undefined json value to enum (where the first map entry above is the default) +json jPi = 3.14; +assert(jPi.get() == TS_INVALID ); +``` + +## Notes + +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()`, 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. diff --git a/doc/mkdocs/docs/features/iterators.md b/doc/mkdocs/docs/features/iterators.md new file mode 100644 index 00000000..a8b88e2d --- /dev/null +++ b/doc/mkdocs/docs/features/iterators.md @@ -0,0 +1,155 @@ +# Iterators + +## Overview + +A `basic_json` value is a container and allows access via iterators. Depending on the value type, `basic_json` stores zero or more values. + +As for other containers, `begin()` returns an iterator to the first value and `end()` returns an iterator to the value following the last value. The latter iterator is a placeholder and cannot be dereferenced. In case of null values, empty arrays, or empty objects, `begin()` will return `end()`. + +![Illustration from cppreference.com](../images/range-begin-end.svg) + +### Iteration order for objects + +When iterating over objects, values are ordered with respect to the `object_comparator_t` type which defaults to `std::less`. See the [types documentation](types.md#key-order) for more information. + +??? example + + ```cpp + // create JSON object {"one": 1, "two": 2, "three": 3} + json j; + j["one"] = 1; + j["two"] = 2; + j["three"] = 3; + + for (auto it = j.begin(); it != j.end(); ++it) + { + std::cout << *it << std::endl; + } + ``` + + Output: + + ```json + 1 + 3 + 2 + ``` + + The reason for the order is the lexicographic ordering of the object keys "one", "three", "two". + +### Access object key during iteration + +The JSON iterators have two member functions, `key()` and `value()` to access the object key and stored value, respectively. When calling `key()` on a non-object iterator, an [invalid_iterator.207](../home/exceptions.md#jsonexceptioninvalid_iterator207) exception is thrown. + +??? example + + ```cpp + // create JSON object {"one": 1, "two": 2, "three": 3} + json j; + j["one"] = 1; + j["two"] = 2; + j["three"] = 3; + + for (auto it = j.begin(); it != j.end(); ++it) + { + std::cout << it.key() << " : " << it.value() << std::endl; + } + ``` + + Output: + + ```json + one : 1 + three : 3 + two : 2 + ``` + +### Range-based for loops + +C++11 allows to use range-based for loops to iterate over a container. + +```cpp +for (auto it : j_object) +{ + // "it" is of type json::reference and has no key() member + std::cout << "value: " << it << '\n'; +} +``` + +For this reason, the `items()` function allows to access `iterator::key()` and `iterator::value()` during range-based for loops. In these loops, a reference to the JSON values is returned, so there is no access to the underlying iterator. + +```cpp +for (auto& el : j_object.items()) +{ + std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; +} +``` + +The items() function also allows to use structured bindings (C++17): + +```cpp +for (auto& [key, val] : j_object.items()) +{ + std::cout << "key: " << key << ", value:" << val << '\n'; +} +``` + +!!! note + + When iterating over an array, `key()` will return the index of the element as string. For primitive types (e.g., numbers), `key()` returns an empty string. + +!!! warning + + Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exeeds the iteration. See for more information. + +### Reverse iteration order + +`rbegin()` and `rend()` return iterators in the reverse sequence. + +![Illustration from cppreference.com](../images/range-rbegin-rend.svg) + +??? example + + ```cpp + json j = {1, 2, 3, 4}; + + for (auto it = j.begin(); it != j.end(); ++it) + { + std::cout << *it << std::endl; + } + ``` + + Output: + + ```json + 4 + 3 + 2 + 1 + ``` + +### Iterating strings and binary values + +Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe the underlying string or binary array is empty. + +??? example + + ```cpp + json j = "Hello, world"; + for (auto it = j.begin(); it != j.end(); ++it) + { + std::cout << *it << std::endl; + } + ``` + + Output: + + ```json + "Hello, world" + ``` + +## Iterator invalidation + +| Operations | invalidated iterators | +| ---------- | --------------------- | +| `clear` | all | diff --git a/doc/mkdocs/docs/features/json_patch.md b/doc/mkdocs/docs/features/json_patch.md new file mode 100644 index 00000000..24cebdd9 --- /dev/null +++ b/doc/mkdocs/docs/features/json_patch.md @@ -0,0 +1,45 @@ +# JSON Patch and Diff + +## Patches + +JSON Patch ([RFC 6902](https://tools.ietf.org/html/rfc6902)) defines a JSON document structure for expressing a sequence of operations to apply to a JSON) document. With the `patch` function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. + +??? example + + The following code shows how a JSON patch is applied to a value. + + ```cpp + --8<-- "examples/patch.cpp" + ``` + + Output: + + ```json + --8<-- "examples/patch.output" + ``` + +## Diff + +The library can also calculate a JSON patch (i.e., a **diff**) given two JSON values. + +!!! success "Invariant" + + For two JSON values *source* and *target*, the following code yields always true: + + ```cüü + source.patch(diff(source, target)) == target; + ``` + +??? example + + The following code shows how a JSON patch is created as a diff for two JSON values. + + ```cpp + --8<-- "examples/diff.cpp" + ``` + + Output: + + ```json + --8<-- "examples/diff.output" + ``` diff --git a/doc/mkdocs/docs/features/json_pointer.md b/doc/mkdocs/docs/features/json_pointer.md new file mode 100644 index 00000000..b95c5bc0 --- /dev/null +++ b/doc/mkdocs/docs/features/json_pointer.md @@ -0,0 +1,15 @@ +# JSON Pointer + +The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. + +```cpp +// a JSON value +json j_original = R"({ + "baz": ["one", "two", "three"], + "foo": "bar" +})"_json; + +// access members with a JSON pointer (RFC 6901) +j_original["/baz/1"_json_pointer]; +// "two" +``` diff --git a/doc/mkdocs/docs/features/merge_patch.md b/doc/mkdocs/docs/features/merge_patch.md new file mode 100644 index 00000000..84e0ab02 --- /dev/null +++ b/doc/mkdocs/docs/features/merge_patch.md @@ -0,0 +1,20 @@ +# JSON Merge Patch + +The library supports JSON Merge Patch ([RFC 7386](https://tools.ietf.org/html/rfc7386)) as a patch format. +The merge patch format is primarily intended for use with the HTTP PATCH method as a means of describing a set of modifications to a target resource's content. This function applies a merge patch to the current JSON value. + +Instead of using [JSON Pointer](json_pointer.md) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified. + +??? example + + The following code shows how a JSON Merge Patch is applied to a JSON document. + + ```cpp + --8<-- "examples/merge_patch.cpp" + ``` + + Output: + + ```json + --8<-- "examples/merge_patch.output" + ``` diff --git a/doc/mkdocs/docs/features/parsing/index.md b/doc/mkdocs/docs/features/parsing/index.md new file mode 100644 index 00000000..5cf59bfe --- /dev/null +++ b/doc/mkdocs/docs/features/parsing/index.md @@ -0,0 +1,13 @@ +# Overview + +!!! note + + This page is under construction. + +## Input + +## SAX vs. DOM parsing + +## Exceptions + +See [parsing and exceptions](parse_exceptions.md). diff --git a/doc/mkdocs/docs/features/parsing/parse_exceptions.md b/doc/mkdocs/docs/features/parsing/parse_exceptions.md new file mode 100644 index 00000000..b882e0b5 --- /dev/null +++ b/doc/mkdocs/docs/features/parsing/parse_exceptions.md @@ -0,0 +1,114 @@ +# Parsing and exceptions + +When the input is not valid JSON, an exception of type [`parse_error`](../../home/exceptions.md#parse-errors) is thrown. This exception contains the position in the input where the error occurred, together with a diagnostic message and the last read input token. The exceptions page contains a [list of examples for parse error exceptions](../../home/exceptions.md#parse-errors). In case you process untrusted input, always enclose your code with a `#!cpp try`/`#!cpp catch` block, like + +```cpp +json j; +try +{ + j = json::parse(my_input); +} +catch (json::exception::parse_error& ex) +{ + std::cerr << "parse error at byte " << ex.byte << std::endl; +} +``` + +In case exceptions are undesired or not supported by the environment, there are different ways to proceed: + + +## Switch off exceptions + +The `parse()` function accepts as last parameter a `#!cpp bool` variable `allow_exceptions` which controls whether an exception is thrown when a parse error occurs (`#!cpp true`, default) or whether a discarded value should be returned (`#!cpp false`). + +```cpp +json j = json::parse(my_input, nullptr, false); +if (j.is_discarded()) +{ + std::cerr << "parse error" << std::endl; +} +``` + +Note there is no diagnostic information available in this scenario. + +## Use accept() function + +Alternatively, function `accept()` can be used which does not return a `json` value, but a `#!cpp bool` indicating whether the input is valid JSON. + +```cpp +if (!json::accept(my_input)) +{ + std::cerr << "parse error" << std::endl; +} +``` + +Again, there is no diagnostic information available. + + +## User-defined SAX interface + +Finally, you can implement the [SAX interface](sax_interface.md) and decide what should happen in case of a parse error. + +This function has the following interface: + +```cpp +bool parse_error(std::size_t position, + const std::string& last_token, + const json::exception& ex); +``` + +The return value indicates whether the parsing should continue, so the function should usually return `#!cpp false`. + +??? example + + ```cpp + #include + #include "json.hpp" + + using json = nlohmann::json; + + class sax_no_exception : public nlohmann::detail::json_sax_dom_parser + { + public: + sax_no_exception(json& j) + : nlohmann::detail::json_sax_dom_parser(j, false) + {} + + bool parse_error(std::size_t position, + const std::string& last_token, + const json::exception& ex) + { + std::cerr << "parse error at input byte " << position << "\n" + << ex.what() << "\n" + << "last read: \"" << last_token << "\"" + << std::endl; + return false; + } + }; + + int main() + { + std::string myinput = "[1,2,3,]"; + + json result; + sax_no_exception sax(result); + + bool parse_result = json::sax_parse(myinput, &sax); + if (!parse_result) + { + std::cerr << "parsing unsuccessful!" << std::endl; + } + + std::cout << "parsed value: " << result << std::endl; + } + ``` + + Output: + + ``` + parse error at input byte 8 + [json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal + last read: "3,]" + parsing unsuccessful! + parsed value: [1,2,3] + ``` diff --git a/doc/mkdocs/docs/features/parsing/parser_callbacks.md b/doc/mkdocs/docs/features/parsing/parser_callbacks.md new file mode 100644 index 00000000..dbf88849 --- /dev/null +++ b/doc/mkdocs/docs/features/parsing/parser_callbacks.md @@ -0,0 +1,79 @@ +# Parser Callbacks + +## Overview + +With a parser callback function, the result of parsing a JSON text can be influenced. When passed to `parse`, it is called on certain events +(passed as `parse_event_t` via parameter `event`) with a set recursion depth `depth` and context JSON value `parsed`. The return value of the +callback function is a boolean indicating whether the element that emitted the callback shall be kept or not. + +The type of the callback function is: + +```cpp +template +using parser_callback_t = + std::function; +``` + + +## Callback event types + +We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values +of the parameters `depth`, `event`, and `parsed`. + +parameter `event` | description | parameter `depth` | parameter `parsed` +------------------ | ----------- | ------------------ | ------------------- +`parse_event_t::object_start` | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded +`parse_event_t::key` | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key +`parse_event_t::object_end` | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object +`parse_event_t::array_start` | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded +`parse_event_t::array_end` | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array +`parse_event_t::value` | the parser finished reading a JSON value | depth of the value | the parsed JSON value + +??? example + + When parsing the following JSON text, + + ```json + { + "name": "Berlin", + "location": [ + 52.519444, + 13.406667 + ] + } + ``` + + these calls are made to the callback function: + + | event | depth | parsed | + | -------------- | ----- | ------ | + | `object_start` | 0 | *discarded* | + | `key` | 1 | `#!json "name"` | + | `value` | 1 | `#!json "Berlin"` | + | `key` | 1 | `#!json "location"` | + | `array_start` | 1 | *discarded* | + | `value` | 2 | `#!json 52.519444` | + | `value` | 2 | `#!json 13.406667` | + | `array_end` | 1 | `#!json [52.519444,13.406667]` | + | `object_end` | 0 | `#!json {"location":[52.519444,13.406667],"name":"Berlin"}` | + +## Return value + +Discarding a value (i.e., returning `#!c false`) has different effects depending on the context in which function was called: + +- Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. +- In case a value outside a structured type is skipped, it is replaced with `#!json null`. This case happens if the top-level element is skipped. + +??? example + + The example below demonstrates the `parse()` function with and without callback function. + + ```cpp + --8<-- "examples/parse__string__parser_callback_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/parse__string__parser_callback_t.output" + ``` diff --git a/doc/mkdocs/docs/features/parsing/sax_interface.md b/doc/mkdocs/docs/features/parsing/sax_interface.md new file mode 100644 index 00000000..ef83a532 --- /dev/null +++ b/doc/mkdocs/docs/features/parsing/sax_interface.md @@ -0,0 +1,65 @@ +# SAX Interface + +The library uses a SAX-like interface with the following functions: + +```plantuml +interface json::sax_t { + + {abstract} bool null() + + + {abstract} bool boolean(bool val) + + + {abstract} bool number_integer(number_integer_t val) + + {abstract} bool number_unsigned(number_unsigned_t val) + + + {abstract} bool number_float(number_float_t val, const string_t& s) + + + {abstract} bool string(string_t& val) + + + {abstract} bool start_object(std::size_t elements) + + {abstract} bool end_object() + + {abstract} bool start_array(std::size_t elements) + + {abstract} bool end_array() + + {abstract} bool key(string_t& val) + + + {abstract} bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) +} +``` + +```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 json::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` 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 `#!cpp 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 `#!cpp bool` indicating the result of the last executed SAX event. It does not return `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`. diff --git a/doc/mkdocs/docs/features/types.md b/doc/mkdocs/docs/features/types.md new file mode 100644 index 00000000..94e40cba --- /dev/null +++ b/doc/mkdocs/docs/features/types.md @@ -0,0 +1,267 @@ +# Types + +This page gives an overview how JSON values are stored and how this can be configured. + +## Overview + +By default, JSON values are stored as follows: + +| JSON type | C++ type | +| --------- | -------- | +| object | `std::map` | +| array | `std::vector` | +| null | `std::nullptr_t` | +| string | `std::string` | +| boolean | `bool` | +| number | `std::int64_t`, `std::uint64_t`, and `double` | + +Note there are three different types for numbers - when parsing JSON text, the best fitting type is chosen. + +## Storage + +```plantuml +enum value_t { + null + object + array + string + boolean + number_integer + number_unsigned + number_float + binary + discarded +} + +class json_value << (U,orchid) >> { + object_t* object + array_t* array + string_t* string + binary_t* binary + boolean_t boolean + number_integer_t number_integer + number_unsigned_t number_unsigned + number_float_t number_float +} + +class basic_json { + -- type and value -- + value_t m_type + json_value m_value + -- derived types -- + + typedef object_t + + typedef array_t + + typedef binary_t + + typedef boolean_t + + typedef number_integer_t + + typedef number_unsigned_t + + typedef number_float_t +} + +basic_json .. json_value +basic_json .. value_t +``` + +## Template arguments + +The data types to store a JSON value are derived from the template arguments passed to class `basic_json`: + +```cpp +template< + template class ObjectType = std::map, + template class ArrayType = std::vector, + class StringType = std::string, + class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = adl_serializer, + class BinaryType = std::vector +> +class basic_json; +``` + +Type `json` is an alias for `basic_json<>` and uses the default types. + +From the template arguments, the following types are derived: + +```cpp +using object_comparator_t = std::less<>; +using object_t = ObjectType>>; + +using array_t = ArrayType>; + +using string_t = StringType; + +using boolean_t = BooleanType; + +using number_integer_t = NumberIntegerType; +using number_unsigned_t = NumberUnsignedType; +using number_float_t = NumberFloatType; + +using binary_t = nlohmann::byte_container_with_subtype; +``` + + +## Objects + +[RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: + +> An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array. + +### Default type + +With the default values for *ObjectType* (`std::map`), *StringType* (`std::string`), and *AllocatorType* (`std::allocator`), the default value for `object_t` is: + +```cpp +std::map< + std::string, // key_type + basic_json, // value_type + std::less<>, // key_compare + std::allocator> // allocator_type +> +``` + +### Behavior + +The choice of `object_t` influences the behavior of the JSON class. With the default type, objects have the following behavior: + +- When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings. +- When the names within an object are not unique, it is unspecified which one of the values for a given key will be chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or `#!json {"key": 2}`. +- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see `dump`) in this order. For instance, both `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored and serialized as `#!json {"a": 2, "b": 1}`. +- When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be treated as equal. + +### Key order + +The order name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. + +### Limits + +[RFC 7159](http://rfc7159.net/rfc7159) specifies: + +> An implementation may set limits on the maximum depth of nesting. + +In this class, the object's limit of nesting is not explicitly constrained. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the `max_size` function of a JSON object. + +### Storage + +Objects are stored as pointers in a `basic_json` type. That is, for any access to object values, a pointer of type `object_t*` must be dereferenced. + + +## Arrays + +[RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: + +> An array is an ordered sequence of zero or more values. + +### Default type + +With the default values for *ArrayType* (`std::vector`) and *AllocatorType* (`std::allocator`), the default value for `array_t` is: + +```cpp +std::vector< + basic_json, // value_type + std::allocator // allocator_type +> +``` + +### Limits + +[RFC 7159](http://rfc7159.net/rfc7159) specifies: + +> An implementation may set limits on the maximum depth of nesting. + +In this class, the array's limit of nesting is not explicitly constrained. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the `max_size` function of a JSON array. + +### Storage + +Arrays are stored as pointers in a `basic_json` type. That is, for any access to array values, a pointer of type `array_t*` must be dereferenced. + + +## Strings + +[RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: + +> A string is a sequence of zero or more Unicode characters. + +Unicode values are split by the JSON class into byte-sized characters during deserialization. + +### Default type + +With the default values for *StringType* (`std::string`), the default value for `string_t` is `#!cpp std::string`. + +### Encoding + +Strings are stored in UTF-8 encoding. Therefore, functions like `std::string::size()` or `std::string::length()` return the number of **bytes** in the string rather than the number of characters or glyphs. + +### String comparison + +[RFC 7159](http://rfc7159.net/rfc7159) states: + +> Software implementations are typically required to test names of object members for equality. Implementations that transform the textual representation into sequences of Unicode code units and then perform the comparison numerically, code unit by code unit, are interoperable in the sense that implementations will agree in all cases on equality or inequality of two strings. For example, implementations that compare strings with escaped characters unconverted may incorrectly find that `"a\\b"` and `"a\u005Cb"` are not equal. + +This implementation is interoperable as it does compare strings code unit by code unit. + +### Storage + +String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type `string_t*` must be dereferenced. + + +## Booleans + +[RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a type which differentiates the two literals `true` and `false`. + +### Default type + +With the default values for *BooleanType* (`#!cpp bool`), the default value for `boolean_t` is `#!cpp bool`. + +### Storage + +Boolean values are stored directly inside a `basic_json` type. + +## Numbers + +[RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: + +> The representation of numbers is similar to that used in most programming languages. A number is represented in base 10 using decimal digits. It contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part. Leading zeros are not allowed. (...) Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted. + +This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, `number_integer_t`, `number_unsigned_t`, and `number_float_t` are used. + +### Default types + +With the default values for *NumberIntegerType* (`std::int64_t`), the default value for `number_integer_t` is `std::int64_t`. +With the default values for *NumberUnsignedType* (`std::uint64_t`), the default value for `number_unsigned_t` is `std::uint64_t`. +With the default values for *NumberFloatType* (`#!cpp double`), the default value for `number_float_t` is `#!cpp double`. + +### Default behavior + +- The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `#!c 010` will be serialized to `#!c 8`. During deserialization, leading zeros yield an error. +- Not-a-number (NaN) values will be serialized to `#!json null`. + +### Limits + +[RFC 7159](http://rfc7159.net/rfc7159) specifies: + +> An implementation may set limits on the range and precision of numbers. + +When the default type is used, the maximal integer number that can be stored is `#!c 9223372036854775807` (`INT64_MAX`) and the minimal integer number that can be stored is `#!c -9223372036854775808` (`INT64_MIN`). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as `number_unsigned_t` or `number_float_t`. + +When the default type is used, the maximal unsigned integer number that can be stored is `#!c 18446744073709551615` (`UINT64_MAX`) and the minimal integer number that can be stored is `#!c 0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as `number_integer_t` or `number_float_t`. + +[RFC 7159](http://rfc7159.net/rfc7159) further states: + +> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are interoperable in the sense that implementations will agree exactly on their numeric values. + +As this range is a subrange of the exactly supported range [`INT64_MIN`, `INT64_MAX`], this class's integer type is interoperable. + +[RFC 7159](http://rfc7159.net/rfc7159) states: + +> This specification allows implementations to set limits on the range and precision of numbers accepted. Since software that implements IEEE 754-2008 binary64 (double precision) numbers is generally available and widely used, good interoperability can be achieved by implementations that expect no more precision or range than these provide, in the sense that implementations will approximate JSON numbers within the expected precision. + +This implementation does exactly follow this approach, as it uses double precision floating-point numbers. Note values smaller than `#!c -1.79769313486232e+308` and values greater than `#!c 1.79769313486232e+308` will be stored as NaN internally and be serialized to `#!json null`. + +### Storage + +Integer number values, unsigned integer number values, and floating-point number values are stored directly inside a `basic_json` type. diff --git a/doc/mkdocs/docs/home/code_of_conduct.md b/doc/mkdocs/docs/home/code_of_conduct.md new file mode 100644 index 00000000..770b8173 --- /dev/null +++ b/doc/mkdocs/docs/home/code_of_conduct.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mail@nlohmann.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/doc/mkdocs/docs/home/design_goals.md b/doc/mkdocs/docs/home/design_goals.md new file mode 100644 index 00000000..91b38752 --- /dev/null +++ b/doc/mkdocs/docs/home/design_goals.md @@ -0,0 +1,17 @@ +# Design goals + +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: + +- **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. + +- **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. + +- **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). + +Other aspects were not so important to us: + +- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). 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. + +- **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. + +See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. diff --git a/doc/mkdocs/docs/home/exceptions.md b/doc/mkdocs/docs/home/exceptions.md new file mode 100644 index 00000000..92dfb43b --- /dev/null +++ b/doc/mkdocs/docs/home/exceptions.md @@ -0,0 +1,801 @@ +# Exceptions + +## Overview + +### Base type + +All exceptions inherit from class `json::exception` (which in turn inherits from `std::exception`). It is used as the base class for all exceptions thrown by the `basic_json` class. This class can hence be used as "wildcard" to catch exceptions. + +```plantuml +std::exception <|-- json::exception +json::exception <|-- json::parse_error +json::exception <|-- json::invalid_iterator +json::exception <|-- json::type_error +json::exception <|-- json::out_of_range +json::exception <|-- json::other_error + +interface std::exception {} + +class json::exception { + + const int id + + const char* what() const +} + +class json::parse_error { + + const std::size_t byte +} +``` + +### Switch off exceptions + +Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`). + +Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. + +## Parse errors + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Exceptions have ids 1xx. + +!!! info "Byte index" + + Member `byte` holds the byte index of the last read character in the input + file. + + For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +??? example + + The following code shows how a `parse_error` exception can be caught. + + ```cpp + --8<-- "examples/parse_error.cpp" + ``` + + Output: + + ``` + --8<-- "examples/parse_error.output" + ``` + + +### json.exception.parse_error.101 + +This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member `byte` indicates the error position. + +!!! failure "Example message" + + Input ended prematurely: + + ``` + [json.exception.parse_error.101] parse error at 2: unexpected end of input; expected string literal + ``` + + No input: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal + ``` + + Control character was not escaped: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \u0009 or \\; last read: '"'" + ``` + + String was not closed: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '"' + ``` + + Invalid number format: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E' + ``` + + `\u` was not be followed by four hex digits: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\u' must be followed by 4 hex digits; last read: '"\u01"' + ``` + + Invalid UTF-8 surrogate pair: + + ``` + [json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '"\uD7FF\uDC00'" + ``` + + Invalid UTF-8 byte: + + ``` + [json.exception.parse_error.101] parse error at line 3, column 24: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '"vous \352t' + ``` + +!!! tip + + - Make sure the input is correctly read. Try to write the input to standard output to check if, for instance, the input file was successfully openened. + - Paste the input to a JSON validator like or a tool like [jq](https://stedolan.github.io/jq/). + +### json.exception.parse_error.102 + +JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. + +!!! failure "Example message" + + ``` + parse error at 14: missing or wrong low surrogate + ``` + +### json.exception.parse_error.103 + +Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. + +!!! failure "Example message" + + ``` + parse error: code points above 0x10FFFF are invalid + ``` + +### json.exception.parse_error.104 + +[RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.104] parse error: JSON patch must be an array of objects + ``` + +### json.exception.parse_error.105 + +An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.105] parse error: operation 'add' must have member 'value' + ``` + ``` + [json.exception.parse_error.105] parse error: operation 'copy' must have string member 'from' + ``` + ``` + [json.exception.parse_error.105] parse error: operation value 'foo' is invalid + ``` + +### json.exception.parse_error.106 + +An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.106] parse error: array index '01' must not begin with '0' + ``` + +### json.exception.parse_error.107 + +A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo' + ``` + +### json.exception.parse_error.108 + +In a JSON Pointer, only `~0` and `~1` are valid escape sequences. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1' + ``` + +### json.exception.parse_error.109 + +A JSON Pointer array index must be a number. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.109] parse error: array index 'one' is not a number + ``` + ``` + [json.exception.parse_error.109] parse error: array index '+1' is not a number + ``` + +### json.exception.parse_error.110 + +When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input + ``` + ``` + [json.exception.parse_error.110] parse error at byte 2: syntax error while parsing UBJSON value: expected end of input; last byte: 0x5A + ``` + +### json.exception.parse_error.112 + +Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0x1C + ``` + +### json.exception.parse_error.113 + +While parsing a map key, a value that is not a string has been read. + +!!! failure "Example message" + + ``` + [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF + ``` + ``` + [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF + ``` + ``` + [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82 + ``` + +### json.exception.parse_error.114 + +The parsing of the corresponding BSON record type is not implemented (yet). + +!!! failure "Example message" + + ``` + [json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF + ``` + +## Iterator errors + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +??? example + + The following code shows how an `invalid_iterator` exception can be caught. + + ```cpp + --8<-- "examples/invalid_iterator.cpp" + ``` + + Output: + + ``` + --8<-- "examples/invalid_iterator.output" + ``` + +### json.exception.invalid_iterator.201 + +The iterators passed to constructor `basic_json(InputIT first, InputIT last)` are not compatible, meaning they do not belong to the same container. Therefore, the range (`first`, `last`) is invalid. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.201] iterators are not compatible + ``` + +### json.exception.invalid_iterator.202 + +In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.202] iterator does not fit current value + ``` + ``` + [json.exception.invalid_iterator.202] iterators first and last must point to objects + ``` + +### json.exception.invalid_iterator.203 + +Either iterator passed to function `erase(IteratorType` first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.203] iterators do not fit current value + ``` + +### json.exception.invalid_iterator.204 + +When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (`begin(),` `end()),` because this is the only way the single stored value is expressed. All other ranges are invalid. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.204] iterators out of range + ``` + +### json.exception.invalid_iterator.205 + +When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the `begin()` iterator, because it is the only way to address the stored value. All other iterators are invalid. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.205] iterator out of range + ``` + +### json.exception.invalid_iterator.206 + +The iterators passed to constructor `basic_json(InputIT first, InputIT last)` belong to a JSON null value and hence to not define a valid range. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.206] cannot construct with iterators from null + ``` + +### json.exception.invalid_iterator.207 + +The `key()` member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.207] cannot use key() for non-object iterators + ``` + + +### json.exception.invalid_iterator.208 + +The `operator[]` to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.208] cannot use operator[] for object iterators + ``` + +### json.exception.invalid_iterator.209 + +The offset operators (`+`, `-`, `+=`, `-=`) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.209] cannot use offsets with object iterators + ``` + +### json.exception.invalid_iterator.210 + +The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (`first`, `last`) is invalid. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.210] iterators do not fit + ``` + +### json.exception.invalid_iterator.211 + +The iterator range passed to the insert function must not be a subrange of the container to insert to. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.211] passed iterators may not belong to container + ``` + +### json.exception.invalid_iterator.212 + +When two iterators are compared, they must belong to the same container. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.212] cannot compare iterators of different containers + ``` + +### json.exception.invalid_iterator.213 + +The order of object iterators cannot be compared, because JSON objects are unordered. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.213] cannot compare order of object iterators + ``` + +### json.exception.invalid_iterator.214 + +Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to `begin()`. + +!!! failure "Example message" + + ``` + [json.exception.invalid_iterator.214] cannot get value + ``` + + +## Type errors + +This exception is thrown in case of a type error; that is, a library function is executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +??? example + + The following code shows how a `type_error` exception can be caught. + + ```cpp + --8<-- "examples/type_error.cpp" + ``` + + Output: + + ``` + --8<-- "examples/type_error.output" + ``` + +### json.exception.type_error.301 + +To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. + +!!! failure "Example message" + + ``` + [json.exception.type_error.301] cannot create object from initializer list + ``` + +### json.exception.type_error.302 + +During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.302] type must be object, but is null + ``` + ``` + [json.exception.type_error.302] type must be string, but is object + ``` + +### json.exception.type_error.303 + +To retrieve a reference to a value stored in a `basic_json` object with `get_ref`, the type of the reference must match the value type. For instance, for a JSON array, the `ReferenceType` must be `array_t &`. + +!!! failure "Example message" + + ``` + [json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object + ``` + ``` + [json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number" + ``` + +### json.exception.type_error.304 + +The `at()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.304] cannot use at() with string + ``` + ``` + [json.exception.type_error.304] cannot use at() with number + ``` + +### json.exception.type_error.305 + +The `operator[]` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.305] cannot use operator[] with a string argument with array + ``` + ``` + [json.exception.type_error.305] cannot use operator[] with a numeric argument with object + ``` + +### json.exception.type_error.306 + +The `value()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.306] cannot use value() with number + ``` + +### json.exception.type_error.307 + +The `erase()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.307] cannot use erase() with string + ``` + +### json.exception.type_error.308 + +The `push_back()` and `operator+=` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.308] cannot use push_back() with string + ``` + +### json.exception.type_error.309 + +The `insert()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.309] cannot use insert() with array + ``` + ``` + [json.exception.type_error.309] cannot use insert() with number + ``` + +### json.exception.type_error.310 + +The `swap()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.310] cannot use swap() with number + ``` + +### json.exception.type_error.311 + +The `emplace()` and `emplace_back()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.311] cannot use emplace() with number + ``` + ``` + [json.exception.type_error.311] cannot use emplace_back() with number + ``` + +### json.exception.type_error.312 + +The `update()` member functions can only be executed for certain JSON types. + +!!! failure "Example message" + + ``` + [json.exception.type_error.312] cannot use update() with array + ``` + +### json.exception.type_error.313 + +The `unflatten` function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. + +!!! failure "Example message" + + ``` + [json.exception.type_error.313] invalid value to unflatten + ``` + +### json.exception.type_error.314 + +The `unflatten` function only works for an object whose keys are JSON Pointers. + +!!! failure "Example message" + + Calling `unflatten()` on an array `#!json [1,2,3]`: + + ``` + [json.exception.type_error.314] only objects can be unflattened + ``` + +### json.exception.type_error.315 + +The `unflatten()` function only works for an object whose keys are JSON Pointers and whose values are primitive. + +!!! failure "Example message" + + Calling `unflatten()` on an object `#!json {"/1", [1,2,3]}`: + + ``` + [json.exception.type_error.315] values in object must be primitive + ``` + +### json.exception.type_error.316 + +The `dump()` function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. + +!!! failure "Example message" + + Calling `dump()` on a JSON value containing an ISO 8859-1 encoded string: + ``` + [json.exception.type_error.316] invalid UTF-8 byte at index 15: 0x6F + ``` + +!!! tip + + - Store the source file with UTF-8 encoding. + - Pass an error handler as last parameter to the `dump()` function to avoid this exception: + - `json::error_handler_t::replace` will replace invalid bytes sequences with `U+FFFD` + - `json::error_handler_t::ignore` will silently ignore invalid byte sequences + +### json.exception.type_error.317 + +The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) + +!!! failure "Example message" + + Serializing `#!json null` to BSON: + ``` + [json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is null + ``` + Serializing `#!json [1,2,3]` to BSON: + ``` + [json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is array + ``` + +!!! tip + + Encapsulate the JSON value in an object. That is, instead of serializing `#!json true`, serialize `#!json {"value": true}` + + +## Out of range + +This exception is thrown in case a library function is called on an input parameter that exceeds the expected range, for instance in case of array indices or nonexisting object keys. + +Exceptions have ids 4xx. + +??? example + + The following code shows how an `out_of_range` exception can be caught. + + ```cpp + --8<-- "examples/out_of_range.cpp" + ``` + + Output: + + ``` + --8<-- "examples/out_of_range.output" + ``` + +### json.exception.out_of_range.401 + +The provided array index `i` is larger than `size-1`. + +!!! failure "Example message" + + ``` + array index 3 is out of range + ``` + +### json.exception.out_of_range.402 + +The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. + +!!! failure "Example message" + + ``` + array index '-' (3) is out of range + ``` + +### json.exception.out_of_range.403 + +The provided key was not found in the JSON object. + +!!! failure "Example message" + + ``` + key 'foo' not found + ``` + +### json.exception.out_of_range.404 + +A reference token in a JSON Pointer could not be resolved. + +!!! failure "Example message" + + ``` + unresolved reference token 'foo' + ``` + +### json.exception.out_of_range.405 + +The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. + +!!! failure "Example message" + + ``` + JSON pointer has no parent + ``` + +### json.exception.out_of_range.406 + +A parsed number could not be stored as without changing it to NaN or INF. + +!!! failure "Example message" + + ``` + number overflow parsing '10E1000' + ``` + +### json.exception.out_of_range.407 + +UBJSON and BSON only support integer numbers up to 9223372036854775807. + +!!! failure "Example message" + + ``` + number overflow serializing '9223372036854775808' + ``` + +### json.exception.out_of_range.408 + +The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. + +!!! failure "Example message" + + ``` + excessive array size: 8658170730974374167 + ``` + +### json.exception.out_of_range.409 + +Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string. + +!!! failure "Example message" + + ``` + BSON key cannot contain code point U+0000 (at byte 2) + ``` + +## Further exceptions + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +??? example + + The following code shows how an `other_error` exception can be caught. + + ```cpp + --8<-- "examples/other_error.cpp" + ``` + + Output: + + ``` + --8<-- "examples/other_error.output" + ``` + +### json.exception.other_error.501 + +A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +!!! failure "Example message" + + Executing `#!json {"op":"test", "path":"/baz", "value":"bar"}` on `#!json {"baz": "qux"}`: + + ``` + [json.exception.other_error.501] unsuccessful: {"op":"test","path":"/baz","value":"bar"} + ``` diff --git a/doc/mkdocs/docs/home/faq.md b/doc/mkdocs/docs/home/faq.md new file mode 100644 index 00000000..a9b5af08 --- /dev/null +++ b/doc/mkdocs/docs/home/faq.md @@ -0,0 +1,128 @@ +# Frequently Asked Questions (FAQ) + +## Limitations + +### Comments + +!!! question "Questions" + + - Why does the library not support comments? + - Can you add support for JSON5/JSONC/HOCON so that comments are supported? + +This library does not support comments. It does so for three reasons: + +1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript. +2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012: + + > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. + + > Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser. + +3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this. + +This library will not support comments in the future. If you wish to use comments, I see three options: + +1. Strip comments before using this library. +2. Use a different JSON library with comment support. +3. Use a format that natively supports comments (e.g., YAML or JSON5). + + +### Relaxed parsing + +!!! question + + - Can you add an option to ignore trailing commas? + +For the same reason this library does not support [comments](#comments), this library also does not support any feature which would jeopardize interoperability. + + +### Parse errors reading non-ASCII characters + +!!! question "Questions" + + - Why is the parser complaining about a Chinese character? + - Does the library support Unicode? + - I get an exception `[json.exception.parse_error.101] parse error at line 1, column 53: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '"Testé$')"` + +The library supports **Unicode input** as follows: + +- Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 8259](https://tools.ietf.org/html/rfc8259.html#section-8.1). +- `std::u16string` and `std::u32string` can be parsed, assuming UTF-16 and UTF-32 encoding, respectively. These encodings are not supported when reading from files or other input containers. +- Other encodings such as Latin-1 or ISO 8859-1 are **not** supported and will yield parse or serialization errors. +- [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. +- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. +- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. +- 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. + +In most cases, the parser is right to complain, because the input is not UTF-8 encoded. This is especially true for Microsoft Windows where Latin-1 or ISO 8859-1 is often the standard encoding. + + +### Key name in exceptions + +!!! question + + Can I get the key of the object item that caused an exception? + +No, this is not possible. See for a longer discussion. + + +## Serialization issues + + +### Order of object keys + +!!! question "Questions" + + - Why are object keys sorted? + - Why is the insertion order of object keys not preserved? + +By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". + +If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)). + + +### Number precision + +!!! question + + - It seems that precision is lost when serializing a double. + - Can I change the precision for floating-point serialization? + +The library uses `std::numeric_limits::digits10` (15 for IEEE `double`s) digits for serialization. This value is sufficient to guarantee roundtripping. If one uses more than this number of digits of precision, then string -> value -> string is not guaranteed to round-trip. + +!!! quote "[cppreference.com](https://en.cppreference.com/w/cpp/types/numeric_limits/digits10)" + + The value of `std::numeric_limits::digits10` is the number of base-10 digits that can be represented by the type T without change, that is, any number with this many significant decimal digits can be converted to a value of type T and back to decimal form, without change due to rounding or overflow. + +!!! tip + + The website https://float.exposed gives a good insight into the internal storage of floating-point numbers. + + +## Compilation issues + +### Android SDK + +!!! question + + Why does the code not compile with Android SDK? + +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. + +```ini +APP_STL := c++_shared +NDK_TOOLCHAIN_VERSION := clang3.6 +APP_CPPFLAGS += -frtti -fexceptions +``` + +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. + + +### Missing STL function + +!!! question "Questions" + + - Why do I get a compilation error `'to_string' is not a member of 'std'` (or similarly, for `strtod` or `strtof`)? + - Why does the code not compile with MinGW or Android SDK? + +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). diff --git a/doc/mkdocs/docs/home/license.md b/doc/mkdocs/docs/home/license.md new file mode 100644 index 00000000..9211eddd --- /dev/null +++ b/doc/mkdocs/docs/home/license.md @@ -0,0 +1,21 @@ +# License + + + +The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): + +Copyright © 2013-2019 [Niels Lohmann](http://nlohmann.me) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +* * * + +The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) + +The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](http://florian.loitsch.com/) + +The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](http://creativecommons.org/publicdomain/zero/1.0/). diff --git a/doc/mkdocs/docs/home/releases.md b/doc/mkdocs/docs/home/releases.md new file mode 100644 index 00000000..0cb890b0 --- /dev/null +++ b/doc/mkdocs/docs/home/releases.md @@ -0,0 +1,1225 @@ +# Releases + +## v3.7.3 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip) (274 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.7.3/json.hpp) (791 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.7.3/json.hpp.asc) (1 KB) + +Release date: 2019-11-17 +SHA-256: 3b5d2b8f8282b80557091514d8ab97e27f9574336c804ee666fda673a9b59926 (json.hpp), 87b5884741427220d3a33df1363ae0e8b898099fbc59f1c451113f6732891014 (include.zip) + +### Summary + +This release fixes a bug introduced in release 3.7.2 which could yield quadratic complexity in destructor calls. All changes are backward-compatible. + +### :bug: Bug Fixes + +- Removed `reserve()` calls from the destructor which could lead to quadratic complexity. #1837 #1838 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + + +## v3.7.2 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.7.2/include.zip) (274 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.7.2/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.7.2/json.hpp) (791 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.7.2/json.hpp.asc) (1 KB) + +Release date: 2019-11-10 +SHA-256: 0a65fcbbe1b334d3f45c9498e5ee28c3f3b2428aea98557da4a3ff12f0f14ad6 (json.hpp), 67f69c9a93b7fa0612dc1b6273119d2c560317333581845f358aaa68bff8f087 (include.zip) + +### Summary + +Project [bad_json_parsers](https://github.com/lovasoa/bad_json_parsers) tested how JSON parser libraries react on **deeply nested inputs**. It turns out that this library segfaulted at a certain nesting depth. This bug was fixed with this release. **Now the parsing is only bounded by the available memory.** All changes are backward-compatible. + +### :bug: Bug Fixes + +* Fixed a bug that lead to stack overflow for deeply nested JSON values (objects, array) by changing the implementation of the destructor from a recursive to an iterative approach. #832, #1419, #1835 + +### :hammer: Further Changes + +* Added WhiteStone Bolt. #1830 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.7.1 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.7.1/include.zip) (273 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.7.1/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.7.1/json.hpp) (789 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.7.1/json.hpp.asc) (1 KB) + +Release date: 2019-11-06 +SHA-256: b5ba7228f3c22a882d379e93d08eab4349458ee16fbf45291347994eac7dc7ce (json.hpp), 77b9f54b34e7989e6f402afb516f7ff2830df551c3a36973085e2c7a6b1045fe (include.zip) + +### Summary + +This release fixes several small bugs in the library. All changes are backward-compatible. + +### :bug: Bug Fixes + +- Fixed a segmentation fault when serializing `std::int64_t` minimum value. #1708 #1722 +- Fixed the [`contains()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_ab23b04802eb9da97dc3f664e54e09cb3.html#ab23b04802eb9da97dc3f664e54e09cb3) function for JSON Pointers. #1727 #1741 +- Fixed too lax SFINAE guard for conversion from `std::pair` and `std::tuple` to `json`. #1805 #1806 #1825 #1826 +- Fixed some regressions detected by UBSAN. Updated CI to use Clang-Tidy 7.1.0. #1716 #1728 +- Fixed integer truncation in `iteration_proxy`. #1797 +- Updated [Hedley](https://github.com/nemequ/hedley) to v11 to [fix a E2512 error](https://github.com/nemequ/hedley/issues/28) in MSVC. #1799 +- Fixed a compile error in enum deserialization of non non-default-constructible types. #1647 #1821 +- Fixed the conversion from `json` to `std::valarray`. + +### :zap: Improvements + +- The [`items()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) function can now be used with a custom string type. #1765 +- Made [`json_pointer::back`](https://nlohmann.github.io/json/classnlohmann_1_1json__pointer_a213bc67c32a30c68ac6bf06f5195d482.html#a213bc67c32a30c68ac6bf06f5195d482) `const`. #1764 #1769 +- Meson is part of the release archive. #1672 #1694 +- Improved documentation on the Meson and Spack package manager. #1694 #1720 + +### :hammer: Further Changes + +- Added GitHub Workflow with `ubuntu-latest`/GCC 7.4.0 as CI step. +- Added GCC 9 to Travis CI to compile with C++20 support. #1724 +- Added MSVC 2019 to the AppVeyor CI. #1780 +- Added badge to [fuzzing status](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json). +- Fixed some cppcheck warnings. #1760 +- Fixed several typos in the documentation. #1720 #1767 #1803 +- Added documentation on the `JSON_THROW_USER`, `JSON_TRY_USER`, and `JSON_CATCH_USER` macros to control user-defined exception handling. +- Used GitHub's [CODEOWNERS](https://github.com/nlohmann/json/blob/develop/.github/CODEOWNERS) and [SECURITY](https://github.com/nlohmann/json/blob/develop/.github/SECURITY.md) feature. +- Removed `GLOB` from CMake files. #1779 +- Updated to [Doctest](https://github.com/onqtam/doctest) 2.3.5. + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.7.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.7.0/include.zip) (143 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.7.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.7.0/json.hpp) (782 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.7.0/json.hpp.asc) (1 KB) + +Release date: 2019-07-28 +SHA-256: a503214947952b69f0062f572cb74c17582a495767446347ce2e452963fc2ca4 (json.hpp), 541c34438fd54182e9cdc68dd20c898d766713ad6d901fb2c6e28ff1f1e7c10d (include.zip) + +### Summary + +This release introduces a few convenience functions and performs a lot of house keeping (bug fixes and small improvements). All changes are backward-compatible. + +### :sparkles: New Features + +- Add overload of the **[`contains`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab23b04802eb9da97dc3f664e54e09cb3.html#ab23b04802eb9da97dc3f664e54e09cb3) function** to check if a JSON pointer is valid without throwing exceptions, just like its [counterpart for object keys](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9286acdc0578fc66e9346323e69fc0e3.html#a9286acdc0578fc66e9346323e69fc0e3). #1600 +- Add a function **[`to_string`](http://nlohmann.github.io/json/doxygen/namespacenlohmann_a6ce645a0b8717757e096a5b5773b7a16.html#a6ce645a0b8717757e096a5b5773b7a16)** to allow for generic conversion to strings. #916 #1585 +- Add **return value for the [`emplace_back`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_abf29131f898b05aad2c01a9c80e7a002.html#abf29131f898b05aad2c01a9c80e7a002) function**, returning a reference to the added element just like C++17 is [introducing this](https://en.cppreference.com/w/cpp/container/vector/emplace_back) for `std::vector`. #1609 +- Add info how to use the library with the **[pacman](https://wiki.archlinux.org/index.php/pacman) package manager** on MSYS2. #1670 + +### :bug: Bug Fixes + +- Fix an issue where typedefs with certain names yielded a compilation error. #1642 #1643 +- Fix a conversion to `std::string_view` in the unit tests. #1634 #1639 +- Fix MSVC Debug build. #1536 #1570 #1608 +- Fix [`get_to`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a65753c68f06639eda0d355f919564e01.html#a65753c68f06639eda0d355f919564e01) method to clear existing content before writing. #1511 #1555 +- Fix a `-Wc++17-extensions` warning. `nodiscard` attributes are now only used with Clang when `-std=c++17` is used. #1535 #1551 + +### :zap: Improvements + +- Switch from [Catch](https://github.com/philsquared/Catch) to **[doctest](https://github.com/onqtam/doctest)** for the unit tests which speeds up compilation and runtime of the 112,112,308 tests. +- Add an explicit section to the [README](https://github.com/nlohmann/json/blob/develop/README.md) about the **frequently addressed topics** [character encoding](https://github.com/nlohmann/json#character-encoding), [comments in JSON](https://github.com/nlohmann/json#comments-in-json), and the [order of object keys](https://github.com/nlohmann/json#order-of-object-keys). + +### :hammer: Further Changes + +- Use [`GNUInstallDirs`](https://cmake.org/cmake/help/v3.0/module/GNUInstallDirs.html) to set library install directories. #1673 +- Fix links in the [README](https://github.com/nlohmann/json/blob/develop/README.md). #1620 #1621 #1622 #1623 #1625 +- Mention [`json` type](http://nlohmann.github.io/json/doxygen/namespacenlohmann_a2bfd99e845a2e5cd90aeaf1b1431f474.html#a2bfd99e845a2e5cd90aeaf1b1431f474) on the [documentation start page](http://nlohmann.github.io/json/doxygen/index.html). #1616 +- Complete documentation of [`value()` function](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_adcf8ca5079f5db993820bf50036bf45d.html#adcf8ca5079f5db993820bf50036bf45d) with respect to `type_error.302` exception. #1601 +- Fix links in the documentation. #1598 +- Add regression tests for MSVC. #1543 #1570 +- Use **[CircleCI](http://circleci.com)** for [continuous integration](https://circleci.com/gh/nlohmann/json). +- Use **[Doozer](https://doozer.io)** for [continuous integration](https://doozer.io/nlohmann/json) on Linux (CentOS, Raspbian, Fedora) +- Add tests to check each CMake flag (`JSON_BuildTests`, `JSON_Install`, `JSON_MultipleHeaders`, `JSON_Sanitizer`, `JSON_Valgrind`, `JSON_NoExceptions`, `JSON_Coverage`). +- Use [Hedley](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros like `JSON_DEPRECATED`, `JSON_NODISCARD`, `JSON_LIKELY`, `JSON_UNLIKELY`, `JSON_HAS_CPP_14`, or `JSON_HAS_CPP_17`. Functions taking or returning pointers are annotated accordingly when a pointer will not be null. +- Build and run tests on [AppVeyor](https://ci.appveyor.com/project/nlohmann/json) in DEBUG and RELEASE mode. + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.6.1 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip) (136 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.6.1/json.hpp) (711 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.6.1/json.hpp.asc) (1 KB) + +Release date: 2019-03-20 +SHA-256: d2eeb25d2e95bffeb08ebb7704cdffd2e8fca7113eba9a0b38d60a5c391ea09a (json.hpp), 69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf (include.zip) + +### Summary + +This release **fixes a regression and a bug** introduced by the earlier 3.6.0 release. All changes are backward-compatible. + +### :bug: Bug Fixes + +- Fixed regression of #590 which could lead to compilation errors with GCC 7 and GCC 8. #1530 +- Fixed a compilation error when `` was included. #1531 + +### :hammer: Further Changes + +- Fixed a warning for missing field initializers. #1527 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.6.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.6.0/include.zip) (136 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.6.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.6.0/json.hpp) (711 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.6.0/json.hpp.asc) (1 KB) + +Release date: 2019-03-20 +SHA-256: ce9839370f28094c71107c405affb3b08c4a098154988014cbb0800b1c44a831 (json.hpp), 237c5e66e7f8186a02804ce9dbd5f69ce89fe7424ef84adf6142e973bd9532f4 (include.zip) + +ℹ️ **This release introduced a regression. Please update to [version 3.6.1](https://github.com/nlohmann/json/releases/tag/v3.6.1)!** + +### Summary + +This release adds some **convenience functions for JSON Pointers**, introduces a [`contains`]( +http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a0a45fc740637123fdf05fef970f8be47.html#a0a45fc740637123fdf05fef970f8be47) function to check if a key is present in an object, and improves the **performance of integer serialization**. Furthermore, a lot of small bug fixes and improvements have been made. All changes are backward-compatible. + +### :sparkles: New Features + +- Overworked the public interface for JSON Pointers. The creation of JSON Pointers is simplified with [`operator/`]( +http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a90a11fe6c7f37b1746a3ff9cb24b0d53.html#a90a11fe6c7f37b1746a3ff9cb24b0d53) and [`operator/=`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a7395bd0af29ac23fd3f21543c935cdfa.html#a7395bd0af29ac23fd3f21543c935cdfa). JSON Pointers can be inspected with [`empty`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a649252bda4a2e75a0915b11a25d8bcc3.html#a649252bda4a2e75a0915b11a25d8bcc3), [`back`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a6bd5b554c10f15672135c216893eef31.html#a6bd5b554c10f15672135c216893eef31), and [`parent_pointer`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_afdaacce1edb7145e0434e014f0e8685a.html#afdaacce1edb7145e0434e014f0e8685a), and manipulated with [`push_back`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a697d12b5bd6205f8866691b166b7c7dc.html#a697d12b5bd6205f8866691b166b7c7dc) and [`pop_back`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1json__pointer_a4b1ee4d511ca195bed896a3da47e264c.html#a4b1ee4d511ca195bed896a3da47e264c). #1434 +- Added a boolean method [`contains`]( +http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a0a45fc740637123fdf05fef970f8be47.html#a0a45fc740637123fdf05fef970f8be47) to check whether an element exists in a JSON object with a given key. Returns false when called on non-object types. #1471 #1474 + +### :bug: Bug Fixes + +- Fixed a compilation issues with libc 2.12. #1483 #1514 +- Fixed endian conversion on PPC64. #1489 +- Fixed library to compile with GCC 9. #1472 #1492 +- Fixed a compilation issue with GCC 7 on CentOS. #1496 +- Fixed an integer overflow. #1447 +- Fixed buffer flushing in serializer. #1445 #1446 + +### :zap: Improvements + +- The performance of dumping integers has been greatly improved. #1411 +- Added CMake parameter `JSON_Install` to control whether the library should be installed (default: on). #1330 +- Fixed a lot of compiler and linter warnings. #1400 #1435 #1502 +- Reduced required CMake version from 3.8 to 3.1. #1409 #1428 #1441 #1498 +- Added `nodiscard` attribute to `meta()`, `array()`, `object()`, `from_cbor`, `from_msgpack`, `from_ubjson`, `from_bson`, and `parse`. #1433 + +### :hammer: Further Changes + +- Added missing headers. #1500 +- Fixed typos and broken links in README. #1417 #1423 #1425 #1451 #1455 #1491 +- Fixed documentation of parse function. #1473 +- Suppressed warning that cannot be fixed inside the library. #1401 #1468 +- Imroved package manager suppert: + - Updated Buckaroo instructions. #1495 + - Improved Meson support. #1463 + - Added Conda package manager documentation. #1430 + - Added NuGet package manager documentation. #1132 +- Continuous Integration + - Removed unstable or deprecated Travis builders (Xcode 6.4 - 8.2) and added Xcode 10.1 builder. + - Added Clang 7 to Travis CI. + - Fixed AppVeyor x64 builds. #1374 #1414 +- Updated thirdparty libraries: + - Catch 1.12.0 -> 1.12.2 + - Google Benchmark 1.3.0 -> 1.4.1 + - Doxygen 1.8.15 -> 1.8.16 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.5.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.5.0/include.zip) (133 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.5.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.5.0/json.hpp) (693 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.5.0/json.hpp.asc) (1 KB) + +Release date: 2018-12-22 +SHA-256: 8a6dbf3bf01156f438d0ca7e78c2971bca50eec4ca6f0cf59adf3464c43bb9d5 (json.hpp), 3564da9c5b0cf2e032f97c69baedf10ddbc98030c337d0327a215ea72259ea21 (include.zip) + +### Summary + +This release introduces the support for **structured bindings** and reading from **`FILE*`**. Besides, a few bugs have been fixed. All changes are backward-compatible. + +### :sparkles: New Features + +- **Structured bindings** are now supported for JSON objects and arrays via the [`items()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) member function, so finally this code is possible: + ```cpp + for (auto& [key, val] : j.items()) { + std::cout << key << ':' << val << '\n'; + } + ``` + #1388 #1391 + +- Added support for **reading from `FILE*`** to support situations in which streams are nit available or would require too much RAM. #1370 #1392 + +### :bug: Bug Fixes + +- The `eofbit` was not set for input streams when the end of a stream was reached while parsing. #1340 #1343 +- Fixed a bug in the SAX parser for BSON arrays. + +### :zap: Improvements + +- Added support for Clang 5.0.1 (PS4 version). #1341 #1342 + +### :hammer: Further Changes + +- Added a warning for implicit conversions to the documentation: It is not recommended to use implicit conversions when reading **from** a JSON value. Details about this recommendation can be found [here](https://www.github.com/nlohmann/json/issues/958). #1363 +- Fixed typos in the documentation. #1329 #1380 #1382 +- Fixed a C4800 warning. #1364 +- Fixed a `-Wshadow` warning #1346 +- Wrapped `std::snprintf` calls to avoid error in MSVC. #1337 +- Added code to allow installation via Meson. #1345 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.4.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.4.0/include.zip) (132 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.4.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.4.0/json.hpp) (689 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.4.0/json.hpp.asc) (1 KB) + +Release date: 2018-10-30 +SHA-256: 63da6d1f22b2a7bb9e4ff7d6b255cf691a161ff49532dcc45d398a53e295835f (json.hpp), bfec46fc0cee01c509cf064d2254517e7fa80d1e7647fea37cf81d97c5682bdc (include.zip) + +### Summary + +This release introduces three new features: + +- **BSON (Binary JSON)** is next to CBOR, MessagePack, and UBJSON the fourth binary (de)serialization format supported by the library. +- **Adjustable error handlers for invalid Unicode** allows to specify the behavior when invalid byte sequences are serialized. +- **Simplified enum/JSON mapping** with a macro in case the default mapping to integers is not desired. + +Furthermore, some effort has been invested in improving the **parse error messages**. Besides, a few bugs have been fixed. All changes are backward-compatible. + +### :sparkles: New Features + +- The library can read and write a subset of **[BSON](http://bsonspec.org/) (Binary JSON)**. All data types known from JSON are supported, whereas other types more tied to MongoDB such as timestamps, object ids, or binary data are currently not implemented. See [the README](https://github.com/nlohmann/json#binary-formats-bson-cbor-messagepack-and-ubjson) for examples. #1244 #1320 +- The behavior when the library encounters an invalid Unicode sequence during serialization can now be controlled by defining one of three **Unicode error handlers**: (1) throw an exception (default behavior), (2) replace invalid sequences by the Unicode replacement character (U+FFFD), or (3) ignore/filter invalid sequences. See the [documentation of the `dump` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) for examples. #1198 #1314 +- To easily specify a user-defined **enum/JSON mapping**, a macro `NLOHMANN_JSON_SERIALIZE_ENUM` has been introduced. See the [README section](https://github.com/nlohmann/json#specializing-enum-conversion) for more information. #1208 #1323 + +### :bug: Bug Fixes + +- fixed truncation #1286 #1315 +- fixed an issue with std::pair #1299 #1301 +- fixed an issue with std::variant #1292 #1294 +- fixed a bug in the JSON Pointer parser + +### :zap: Improvements + +- The **diagnosis messages for parse errors** have been improved: error messages now indicated line/column positions where possible (in addition to a byte count) and also the context in which the error occurred (e.g., "while parsing a JSON string"). Example: error `parse error at 2: syntax error - invalid string: control character must be escaped; last read: ''` is now reported as `parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \u0009 or \t; last read: ''`. #1280 #1288 #1303 + +### :hammer: Further Changes + +- improved Meson documentation #1305 +- fixed some more linter warnings #1280 +- fixed Clang detection for third-party Google Benchmark library #1277 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.3.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.3.0/include.zip) (123 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.3.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.3.0/json.hpp) (635 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.3.0/json.hpp.asc) (1 KB) + +Release date: 2018-10-05 +SHA-256: f1327bb60c58757a3dd2b0c9c45d49503d571337681d950ec621f8374bcc14d4 (json.hpp), 9588d63557333aaa485e92221ec38014a85a6134e7486fe3441e0541a5a89576 (include.zip) + +### Summary + +This release adds support for **GCC 4.8**. Furthermore, it adds a function [**`get_to`**](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a8a3db7d78f74232d3a6fb8f1abf69709.html#a8a3db7d78f74232d3a6fb8f1abf69709) to write a JSON value to a passed reference. Another topic of this release was the **CMake support** which has been overworked and documented. + +Besides, a lot of bugs have been fixed and slight improvements have been made. All changes are backward-compatible. + +### :sparkles: New Features + +- The library can now also built with **GCC 4.8**. Though this compiler does not fully support C++11, it can successfully compile and run the test suite. Note that bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824) in GCC 4.8 still forbids to use multiline raw strings in arguments to macros. #1257 +- Added new function [**`get_to`**](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a8a3db7d78f74232d3a6fb8f1abf69709.html#a8a3db7d78f74232d3a6fb8f1abf69709) to write a JSON value to a passed reference. The destination type is automatically derived which allows more succinct code compared to the `get` function. #1227 #1231 + +### :bug: Bug Fixes + +- Fixed a bug in the CMake file that made `target_link_libraries` to not properly include `nlohmann_json`. #1243 #1245 #1260 +- Fixed a warning in MSVC 2017 complaining about a constexpr if. #1204 #1268 #1272 +- Fixed a bug that prevented compilation with ICPC. #755 #1222 +- Improved the SFINAE correctness to fix a bug in the conversion operator. #1237 #1238 +- Fixed a `-Wctor-dtor-privacy` warning. #1224 +- Fixed a warning on a lambda in unevaluated context. #1225 #1230 +- Fixed a bug introduced in version 3.2.0 where defining `JSON_CATCH_USER` led to duplicate macro definition of `JSON_INTERNAL_CATCH`. #1213 #1214 +- Fixed a bug that prevented compilation with Clang 3.4.2 in RHEL 7. #1179 #1249 + +### :zap: Improvements + +- Added [documentation on CMake integration](https://github.com/nlohmann/json#cmake) of the library. #1270 +- Changed the CMake file to use `find_package(nlohmann_json)` without installing the library. #1202 +- Improved error messages in case `operator[]` is used with the wrong combination (json.exception.type_error.305) of JSON container type and argument type. Example: "cannot use operator[] with a string argument". #1220 #1221 +- Added a license and version information to the Meson build file. #1252 +- Removed static assertions to indicated missing `to_json` or `from_json` functions as such assertions do not play well with SFINAE. These assertions also led to problems with GMock. #960 #1212 #1228 +- The test suite now does not wait forever if run in a wrong directory and input files are not found. #1262 +- The test suite does not show deprecation warnings for deprecated functions which frequently led to confusion. #1271 + +### :hammer: Further Changes + +- GCC 4.8 and Xcode 10 were added to the [continuous integration suite](https://travis-ci.org/nlohmann/json) at Travis. +- Added [lgtm](https://lgtm.com/projects/g/nlohmann/json/context:cpp) checks to pull requests. +- Added tests for CMake integration. #1260 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + + +## v3.2.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.2.0/include.zip) (124 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.2.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.2.0/json.hpp) (636 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.2.0/json.hpp.asc) (1 KB) + +Release date: 2018-08-20 +SHA-256: ce6b5610a051ec6795fa11c33854abebb086f0fd67c311f5921c3c07f9531b44 (json.hpp), 35ee642558b90e2f9bc758995c4788c4b4d4dec54eef95fb8f38cb4d49c8fc7c (include.zip) + +### Summary + +This release introduces a [**SAX interface**](https://nlohmann.github.io/json/structnlohmann_1_1json__sax.html) to the library. While this may be a very special feature used by only few people, it allowed to unify all functions that consumed input and created some kind of JSON value. Internally, now all existing functions like `parse`, `accept`, `from_cbor`, `from_msgpack`, and `from_ubjson` use the SAX interface with different event processors. This allowed to separate the input processing from the value generation. Furthermore, throwing an exception in case of a parse error is now optional and up to the event processor. Finally, the JSON parser is now non-recursive (meaning it does not use the call stack, but `std::vector` to track the hierarchy of structured values) which allows to process nested input more efficiently. + +Furthermore, the library finally is able to parse from **wide string types**. This is the first step toward opening the library from UTF-8 to UTF-16 and UTF-32. + +This release further fixes several bugs in the library. All changes are backward-compatible. + +### :sparkles: New Features + +- added a parser with a **SAX interface** (#971, #1153) +- support to parse from **wide string types** `std::wstring`, `std::u16string`, and `std::u32string`; the input will be converted to UTF-8 (#1031) +- added support for **`std::string_view`** when using C++17 (#1028) +- allow to **roundtrip `std::map` and `std::unordered_map`** from JSON if key type is not convertible to string; in these cases, values are serialized to arrays of pairs (#1079, #1089, #1133, #1138) + +### :bug: Bug Fixes + +- allow to create `nullptr_t` from JSON allowing to properly roundtrip `null` values (#1169) +- allow compare user-defined string types (#1130) +- better support for algorithms using iterators from `items()` (#1045, #1134) +- added parameter to avoid compilation error with MSVC 2015 debug builds (#1114) +- re-added accidentially skipped unit tests (#1176) +- fixed MSVC issue with `std::swap` (#1168) + +### :zap: Improvements + +- `key()` function for iterators returns a const reference rather than a string copy (#1098) +- binary formats CBOR, MessagePack, and UBJSON now supports `float` as type for floating-point numbers (#1021) + +### :hammer: Further Changes + +- changed issue templates +- improved continuous integration: added builders for Xcode 9.3 and 9.4, added builders for GCC 8 and Clang 6, added builder for MinGW, added builders for MSVC targeting x86 +- required CMake version is now at least 3.8 (#1040) +- overworked CMake file wrt. packaging (#1048) +- added package managers: Spack (#1041) and CocoaPods (#1148) +- fixed Meson include directory (#1142) +- preprocessor macro `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK` can skip the rejection of unsupported compilers - use at your own risk! (#1128) +- preprocessor macro `JSON_INTERNAL_CATCH`/`JSON_INTERNAL_CATCH_USER` allows to control the behavior of exception handling inside the library (#1187) +- added note on `char` to JSON conversion +- added note how to send security-related issue via encrypted email +- removed dependency to `std::stringstream` (#1117) +- added SPDX-License-Identifier +- added updated JSON Parsing Test Suite, described in [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.php) +- updated to Catch 1.12.0 + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + + + +## v3.1.2 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.1.2/include.zip) (115 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.1.2/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.1.2/json.hpp) (582 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.1.2/json.hpp.asc) (1 KB) + +Release date: 2018-03-14 +SHA-256: fbdfec4b4cf63b3b565d09f87e6c3c183bdd45c5be1864d3fcb338f6f02c1733 (json.hpp), 495362ee1b9d03d9526ba9ccf1b4a9c37691abe3a642ddbced13e5778c16660c (include.zip) + +### Summary + +This release fixes several bugs in the library. All changes are backward-compatible. + +### :bug: Bug Fixes + +- Fixed a **memory leak** occurring in the parser callback (#1001). +- Different **specializations of `basic_json`** (e.g., using different template arguments for strings or objects) can now be used in assignments (#972, #977, #986). +- Fixed a logical error in an iterator range check (#992). + +### :zap: Improvements + +- The parser and the serialization now support **user-defined string types** (#1006, #1009). + +### :hammer: Further Changes + +- **[Clang Analyzer](http://clang-analyzer.llvm.org)** is now used as additional static analyzer; see `make clang_analyze`. +- Overworked [README](https://github.com/nlohmann/json/blob/develop/README.md) by adding links to the [documentation](https://nlohmann.github.io/json/) (#981). + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + + +## v3.1.1 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.1.1/include.zip) (114 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.1.1/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.1.1/json.hpp) (577 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.1.1/json.hpp.asc) (1 KB) + +Release date: 2018-02-13 +SHA-256: e14ce5e33d6a2daf748026bd4947f3d9686ca4cfd53d10c3da46a0a9aceb7f2e (json.hpp), fde771d4b9e4f222965c00758a2bdd627d04fb7b59e09b7f3d1965abdc848505 (include.zip) + +### Summary + +This release fixes several bugs in the library. All changes are backward-compatible. + +### :bug: Bug Fixes + +- Fixed parsing of **CBOR strings with indefinite length** (#961). Earlier versions of this library misinterpreted the CBOR standard and rejected input with the `0x7F` start byte. +- Fixed user-defined **conversion to vector type** (#924, #969). A wrong SFINAE check rejected code though a user-defined conversion was provided. +- Fixed documentation of the parser behavior for **objects with duplicate keys** (#963). The exact behavior is not specified by [RFC 8259](https://tools.ietf.org/html/rfc8259) and the library now also provides no guarantee which object key is stored. +- Added check to detect memory **overflow when parsing UBJSON containers** (#962). The optimized UBJSON format allowed for specifying an array with billions of `null` elements with a few bytes and the library did not check whether this size exceeded `max_size()`. + +### :hammer: Further Changes + +- [Code coverage](https://coveralls.io/github/nlohmann/json) is now calculated for the individual header files, allowing to find uncovered lines more quickly than by browsing through the single header version (#953, #957). +- A Makefile target `run_benchmarks` was added to quickly build and run the benchmark suite. +- The documentation was harmonized with respect to the header inclusion (#955). Now all examples and the README use `#include ` to allow for selecting `single_include` or `include` or whatever installation folder as include directory. +- Added note on how to use the library with the [cget](http://cget.readthedocs.io/en/latest/) package manager (#954). + +### :fire: Deprecated functions + +This release does not deprecate any functions. As an overview, the following functions have been deprecated in earlier versions and will be removed in the next major version (i.e., 4.0.0): + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) are deprecated. Please use the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) instead. +- Functions [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) and [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) are deprecated. Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.1.0 + +!!! summary "Files" + + - [include.zip](https://github.com/nlohmann/json/releases/download/v3.1.0/include.zip) (114 KB) + - [include.zip.asc](https://github.com/nlohmann/json/releases/download/v3.1.0/include.zip.asc) (1 KB) + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.1.0/json.hpp) (577 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.1.0/json.hpp.asc) (1 KB) + +Release date: 2018-02-01 +SHA-256: d40f614d10a6e4e4e80dca9463da905285f20e93116c36d97d4dc1aa63d10ba4 (json.hpp), 2b7234fca394d1e27b7e017117ed80b7518fafbb4f4c13a7c069624f6f924673 (include.zip) + +### Summary + +This release adds support for the [**UBJSON**](http://ubjson.org) format and [**JSON Merge Patch**](https://tools.ietf.org/html/rfc7386). It also contains some minor changes and bug fixes. All changes are backward-compatible. + +### :sparkles: New features + +- The library now supports [**UBJSON**](http://ubjson.org) (Universal Binary JSON Specification) as binary format to read and write JSON values space-efficiently. See the [documentation overview](https://github.com/nlohmann/json/blob/develop/doc/binary_formats.md) for a comparison of the different formats CBOR, MessagePack, and UBJSON. +- [**JSON Merge Patch**](https://tools.ietf.org/html/rfc7386) (RFC 7386) offers an intuitive means to describe patches between JSON values (#876, #877). See the documentation of [`merge_patch`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a0ec0cd19cce42ae6071f3cc6870ea295.html#a0ec0cd19cce42ae6071f3cc6870ea295) for more information. + +### :zap: Improvements + +- The library now uses the **Grisu2 algorithm** for printing floating-point numbers (based on the reference implementation by Florian Loitsch) which produces a short representation which is guaranteed to round-trip (#360, #935, #936). +- The **UTF-8 handling** was further simplified by using the decoder of Björn Hoehrmann in more scenarios. + +### :truck: Reorganization + +- Though the library is released as a single header, its development got more and more complicated. With this release, the header is **split into several files** and the single-header file `json.hpp` can be generated from these development sources. In the repository, folder `include` contains the development sources and `single_include` contains the single `json.hpp` header (#700, #906, #907, #910, #911, #915, #920, #924, #925, #928, #944). +- The split further allowed for a **forward declaration header** `include/nlohmann/json_fwd.hpp` to speed up compilation times (#314). + +### :hammer: Further changes + +- [Google Benchmark](https://github.com/google/benchmark) is now used for micro benchmarks (see `benchmarks` folder, #921). +- The serialization (JSON and binary formats) now properly work with the libraries string template parameter, allowing for optimized string implementations to be used in constraint environments such as embedded software (#941, #950). +- The exceptional behavior can now be overridden by defining macros `JSON_THROW_USER`, `JSON_TRY_USER`, and `JSON_CATCH_USER`, defining the behavior of `throw`, `try` and `catch`, respectively. This allows to switch off C++'s exception mechanism yet still execute user-defined code in case an error condition occurs (#938). +- To facilitate the interplay with [flex](https://github.com/westes/flex) and [Bison](https://www.gnu.org/software/bison/), the library does not use the variable name `yytext` any more as it could clash with macro definitions (#933). +- The library now defines `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and `NLOHMANN_JSON_VERSION_PATCH` to allow for conditional compilation based on the included library version (#943, #948). +- A compilation error with ICC has been fixed (#947). +- Typos and links in the documentation have been fixed (#900, #930). +- A compiler error related to incomplete types has been fixed (#919). +- The tests form the [UTF-8 decoder stress test](http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt) have been added to the test suite. + +### :fire: Deprecated functions + +- Function [`iterator_wrapper`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1592a06bc63811886ade4f9d965045e.html#af1592a06bc63811886ade4f9d965045e) has been deprecated (#874). Since its introduction, the name was up for discussion, as it was too technical. We now introduced the member function [`items()`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_afe3e137ace692efa08590d8df40f58dd.html#afe3e137ace692efa08590d8df40f58dd) with the same semantics. `iterator_wrapper` will be removed in the next major version (i.e., 4.0.0). + +Furthermore, the following functions are deprecated since version 3.0.0 and will be removed in the next major version (i.e., 4.0.0): + +- [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) +- [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) + +Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.0.1 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.0.1/json.hpp) (502 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.0.1/json.hpp.asc) (1 KB) + +Release date: 2017-12-29 +SHA-256: c9b3591f1bb94e723a0cd7be861733a3a555b234ef132be1e9027a0364118c4c + +### Summary + +This release fixes small issues in the implementation of **JSON Pointer** and **JSON Patch**. All changes are backward-compatible. + +### Changes + +- :bug: The **"copy" operation of JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) requests that it is an error if the target path points into a non-existing array or object (see #894 for a detailed description). This release fixes the implementation to detect such invalid target paths and throw an exception. +- :bug: An **array index in a JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) must be an integer. This release fixes the implementation to throw an exception in case invalid array indices such as `10e2` are used. +- :white_check_mark: Added the [JSON Patch tests](https://github.com/json-patch/json-patch-tests) from Byron Ruth and Mike McCabe. +- :memo: Fixed the documentation of the [`at(ptr)` function with JSON Pointers](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a8ab61397c10f18b305520da7073b2b45.html#a8ab61397c10f18b305520da7073b2b45) to list all possible exceptions (see #888). +- :memo: Updated the [container overview documentation](https://nlohmann.github.io/json/) (see #883). +- :wrench: The CMake files now respect the [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/module/CTest.html?highlight=build_testing) option (see #846, #885) +- :rotating_light: Fixed some compiler warnings (see #858, #882). + +### Deprecated functions + +:fire: To unify the interfaces and to improve similarity with the STL, the following functions are deprecated since version 3.0.0 and will be removed in the next major version (i.e., 4.0.0): + +- [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) +- [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) + +Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +## v3.0.0 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v3.0.0/json.hpp) (501 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v3.0.0/json.hpp.asc) (1 KB) + +Release date: 2017-12-17 +SHA-256: 076d4a0cb890a3c3d389c68421a11c3d77c64bd788e85d50f1b77ed252f2a462 + +### Summary + + + +After almost a year, here is finally a new release of JSON for Modern C++, and it is a major one! As we adhere to [semantic versioning](https://semver.org), this means the release includes some breaking changes, so please read the next section carefully before you update. But don't worry, we also added a few new features and put a lot of effort into fixing a lot of bugs and straighten out a few inconsistencies. + +### :boom: Breaking changes + +This section describes changes that change the public API of the library and may require changes in code using a previous version of the library. In section "Moving from 2.x.x to 3.0.0" at the end of the release notes, we describe in detail how existing code needs to be changed. + +- The library now uses [**user-defined exceptions**](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9a0aced019cb1d65bb49703406c84970.html#a9a0aced019cb1d65bb49703406c84970) instead of re-using those defined in `` (#244). This not only allows to add more information to the exceptions (every exception now has an identifier, and parse errors contain the position of the error), but also to easily catch all library exceptions with a single `catch(json::exception)`. +- When strings with a different encoding as UTF-8 were stored in JSON values, their serialization could not be parsed by the library itself, as only UTF-8 is supported. To enforce this library limitation and improve consistency, **non-UTF-8 encoded strings now yield a `json::type_error` exception during serialization** (#838). The check for valid UTF-8 is realized with code from [Björn Hoehrmann](http://bjoern.hoehrmann.de/). +- **NaN and infinity values can now be stored inside the JSON value** without throwing an exception. They are, however, still serialized as `null` (#388). +- The library's iterator tag was changed from RandomAccessIterator to **[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator)** (#593). Supporting RandomAccessIterator was incorrect as it assumed an ordering of values in a JSON objects which are unordered by definition. +- The library does not include the standard headers ``, ``, and `` any more. You may need to add these headers to code relying on them. +- Removed constructor `explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)` which was deprecated in version 2.0.0 (#480). + +### :fire: Deprecated functions + +To unify the interfaces and to improve similarity with the STL, the following functions are now deprecated and will be removed in the next major version (i.e., 4.0.0): + +- [`friend std::istream& operator<<(basic_json&, std::istream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ab7285a92514fcdbe6de505ebaba92ea3.html#ab7285a92514fcdbe6de505ebaba92ea3) +- [`friend std::ostream& operator>>(const basic_json&, std::ostream&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9e06deabe69262c3ffc5533d32856983.html#a9e06deabe69262c3ffc5533d32856983) + +Please use [`friend std::istream& operator>>(std::istream&, basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aaf363408931d76472ded14017e59c9e8.html#aaf363408931d76472ded14017e59c9e8) and [`friend operator<<(std::ostream&, const basic_json&)`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5e34c5435e557d0bf666bd7311211405.html#a5e34c5435e557d0bf666bd7311211405) instead. + +### :sparkles: New features + +With all this breaking and deprecation out of the way, let's talk about features! + +- We improved the **diagnostic information for syntax errors** (#301). Now, an exception [`json::parse_error`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1efc2468e6022be6e35fc2944cabe4d.html#af1efc2468e6022be6e35fc2944cabe4d) is thrown which contains a detailed message on the error, but also a member `byte` to indicate the byte offset in the input where the error occurred. +- We added a **non-throwing syntax check** (#458): The new `accept` function returns a Boolean indicating whether the input is proper JSON. We also added a Boolean parameter `allow_exceptions` to the existing [`parse`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_aa9676414f2e36383c4b181fe856aa3c0.html#aa9676414f2e36383c4b181fe856aa3c0) functions to return a `discarded` value in case a syntax error occurs instead of throwing an exception. +- An [`update`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a1cfa9ae5e7c2434cab4cfe69bffffe11.html#a1cfa9ae5e7c2434cab4cfe69bffffe11) function was added to **merge two JSON objects** (#428). In case you are wondering: the name was inspired by [Python](https://docs.python.org/2/library/stdtypes.html#dict.update). +- The [`insert`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a1b0a4e60d56f1fe80501ed941e122892.html#a1b0a4e60d56f1fe80501ed941e122892) function now also supports an iterator range to add elements to an object. +- The binary exchange formats **CBOR and MessagePack can now be parsed from input streams and written to output streams** (#477). +- Input streams are now only read until the end of a JSON value instead of the end of the input (#367). +- The serialization function [`dump`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) now has two optional parameters `ensure_ascii` to **escape all non-ASCII characters** with `\uxxxx` and an `indent_char` parameter to choose whether to **indent with spaces or tabs** (#654). +- Added **built-in type support** for C arrays (#502), `std::pair` and `std::tuple` (#563, #614), `enum` and `enum class` (#545), `std::vector` (#494). Fixed support for `std::valarray` (#702), `std::array` (#553), and `std::map` (#600, #607). + +### :hammer: Further changes + +Furthermore, there have been a lot of changes under the hood: + +- Replaced the [re2c](http://re2c.org) generated scanner by a self-coded version which allows for a better modularization of the parser and better diagnostics. To test the new scanner, we added millions (8,860,608 to be exact) of unit tests to check all valid and invalid byte sequences of the Unicode standard. +- Google's OSS-Fuzz is still constantly fuzz-testing the library and found several issues that were fixed in this release (#497, #504, #514, #516, #518, #519, #575). +- We now also ignore UTF-8 byte order marks when parsing from an iterator range (#602). +- Values can be now moved from initializer lists (#663). +- Updated to [Catch](https://github.com/catchorg/Catch2) 1.9.7. Unfortunately, Catch2 currently has some performance issues. +- The non-exceptional paths of the library are now annotated with `__builtin_expect` to optimize branch prediction as long as no error occurs. +- MSVC now produces a stack trace in MSVC if a `from_json` or `to_json` function was not found for a user-defined type. We also added a debug visualizer [`nlohmann_json.natvis`](https://github.com/nlohmann/json/blob/develop/nlohmann_json.natvis) for better debugging in MSVC (#844). +- Overworked the documentation and added even more examples. +- The build workflow now relies on CMake and CTest. Special flags can be chosen with CMake, including coverage (`JSON_Coverage`), compilation without exceptions (`JSON_NoExceptions`), LLVM sanitizers (`JSON_Sanitizer`), or execution with Valgrind (`JSON_Valgrind`). +- Added support for package managers Meson (#576), Conan (#566), Hunter (#671, #829), and vcpkg (#753). +- Added CI builders: Xcode 8.3, 9.0, 9.1, and 9.2; GCC 7.2; Clang 3.8, 3.9, 4.0, and 5.0; Visual Studio 2017. The library is further built with C++17 settings on the latest Clang, GCC, and MSVC version to quickly detect new issues. + +### Moving from 2.x.x to 3.0.0 + +#### User-defined Exceptions + +There are five different exceptions inheriting from [`json::exception`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a9a0aced019cb1d65bb49703406c84970.html#a9a0aced019cb1d65bb49703406c84970): + +- [`json::parse_error`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af1efc2468e6022be6e35fc2944cabe4d.html#af1efc2468e6022be6e35fc2944cabe4d) for syntax errors (including the binary formats), +- [`json::invalid_iterator`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_ac13d32f7cbd02d616e71d8dc30dadcbf.html#ac13d32f7cbd02d616e71d8dc30dadcbf) for errors related to iterators, +- [`json::type_error`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a4010e8e268fefd86da773c10318f2902.html#a4010e8e268fefd86da773c10318f2902) for errors where functions were called with the wrong JSON type, +- [`json::out_of_range`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a28f7c2f087274a0012eb7a2333ee1580.html#a28f7c2f087274a0012eb7a2333ee1580) for range errors, and +- [`json::other_error`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a3333a5a8714912adda33a35b369f7b3d.html#a3333a5a8714912adda33a35b369f7b3d) for miscellaneous errors. + +To support these exception, the `try`/`catch` blocks of your code need to be adjusted: + +| new exception | previous exception | +|:--|:--| +| parse_error.101 | invalid_argument | +| parse_error.102 | invalid_argument | +| parse_error.103 | invalid_argument | +| parse_error.104 | invalid_argument | +| parse_error.105 | invalid_argument | +| parse_error.106 | domain_error | +| parse_error.107 | domain_error | +| parse_error.108 | domain_error | +| parse_error.109 | invalid_argument | +| parse_error.110 | out_of_range | +| parse_error.111 | invalid_argument | +| parse_error.112 | invalid_argument | +| invalid_iterator.201 | domain_error | +| invalid_iterator.202 | domain_error | +| invalid_iterator.203 | domain_error | +| invalid_iterator.204 | out_of_range | +| invalid_iterator.205 | out_of_range | +| invalid_iterator.206 | domain_error | +| invalid_iterator.207 | domain_error | +| invalid_iterator.208 | domain_error | +| invalid_iterator.209 | domain_error | +| invalid_iterator.210 | domain_error | +| invalid_iterator.211 | domain_error | +| invalid_iterator.212 | domain_error | +| invalid_iterator.213 | domain_error | +| invalid_iterator.214 | out_of_range | +| type_error.301 | domain_error | +| type_error.302 | domain_error | +| type_error.303 | domain_error | +| type_error.304 | domain_error | +| type_error.305 | domain_error | +| type_error.306 | domain_error | +| type_error.307 | domain_error | +| type_error.308 | domain_error | +| type_error.309 | domain_error | +| type_error.310 | domain_error | +| type_error.311 | domain_error | +| type_error.313 | domain_error | +| type_error.314 | domain_error | +| type_error.315 | domain_error | +| out_of_range.401 | out_of_range | +| out_of_range.402 | out_of_range | +| out_of_range.403 | out_of_range | +| out_of_range.404 | out_of_range | +| out_of_range.405 | domain_error | +| other_error.501 | domain_error | + +#### Handling of NaN and INF + +- If an overflow occurs during parsing a number from a JSON text, an exception [`json::out_of_range`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a28f7c2f087274a0012eb7a2333ee1580.html#a28f7c2f087274a0012eb7a2333ee1580) is thrown so that the overflow is detected early and roundtripping is guaranteed. + +- NaN and INF floating-point values can be stored in a JSON value and are not replaced by null. That is, the basic_json class behaves like `double` in this regard (no exception occurs). However, NaN and INF are serialized to `null`. + +#### Removal of deprecated functions + +Function `explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)` should be replaced by the `parse` function: Let `ss` be a stream and `cb` be a parse callback function. + +Old code: + +```cpp +json j(ss, cb); +``` + +New code: + +```cpp +json j = json::parse(ss, cb); +``` + +If no callback function is used, also the following code works: + +```cpp +json j; +j << ss; +``` + +or + +```cpp +json j; +ss >> j; +``` + +## v2.1.1 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.1.1/json.hpp) (437 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.1.1/json.hpp.asc) (1 KB) + +Release date: 2017-02-25 +SHA-256: faa2321beb1aa7416d035e7417fcfa59692ac3d8c202728f9bcc302e2d558f57 + +### Summary + +This release **fixes a locale-related bug in the parser**. To do so, the whole number handling (lexer, parser, and also the serialization) have been overworked. Furthermore, a lot of small changes added up that were added to this release. All changes are backward-compatible. + +### Changes +- :bug: Locales that have a different character than `.` as decimal separator (e.g., the Norwegian locale `nb_NO.UTF-8`) led to truncated number parsing or parse errors. The library now has been fixed to work with **any locale**. Note that `.` is still the only valid decimal separator for JSON input. +- :bug: Numbers like `1.0` were correctly parsed as floating-point number, but serialized as integer (`1`). Now, **floating-point numbers correctly round trip**. +- :bug: Parsing incorrect JSON numbers with leading 0 (`0123`) could yield a [buffer overflow](https://github.com/nlohmann/json/issues/452). This is fixed now by detecting such errors directly by the lexer. +- :bug: Constructing a JSON value from a pointer was incorrectly interpreted as a Boolean; such code will now yield a compiler error. +- :bug: Comparing a JSON number with `0` led to a comparison with `null`. This is fixed now. +- :bug: All throw calls are now wrapped in macros. +- :lock: Starting during the preparation of this release (since 8 February 2017), commits and released files are **cryptographically signed** with [this GPG key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69). Previous releases have also been signed. +- :sparkles: The parser for MessagePack and CBOR now supports an optional start index parameter to define a byte offset for the parser. +- :rotating_light: Some more warnings have been fixed. With Clang, the code compiles **without warnings** with `-Weverything` (well, it needs `-Wno-documentation-unknown-command` and `-Wno-deprecated-declarations`, but you get the point). +- :hammer: The code can be compiled easier with many Android NDKs by avoiding macros like `UINT8_MAX` which previously required defining a preprocessor macro for compilation. +- :zap: The unit tests now compile two times faster. +- :heavy_plus_sign: [Cotire](https://github.com/sakra/cotire) is used to speed up the build. +- :pencil2: Fixed a lot of typos in the documentation. +- :memo: Added a section to the README file that lists all used [third-party code/tools](https://github.com/nlohmann/json#used-third-party-tools). +- :memo: Added a note on constructing a string value vs. parsing. +- :white_check_mark: The test suite now contains 11202597 unit tests. +- :memo: Improved the [Doxygen documentation](https://nlohmann.github.io/json/) by shortening the template parameters of class `basic_json`. +- :construction_worker: Removed Doozer. +- :construction_worker: Added Codacity. +- :arrow_up: Upgraded Catch to version 1.7.2. + + +## v2.1.0 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.1.0/json.hpp) (426 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.1.0/json.hpp.asc) (1 KB) + +- Release date: 2017-01-28 +- SHA-256: a571dee92515b685784fd527e38405cf3f5e13e96edbfe3f03d6df2e363a767b + +### Summary + +This release introduces a means to convert from/to user-defined types. The release is backwards compatible. + +![conversion](https://cloud.githubusercontent.com/assets/159488/22399173/aebe8f7a-e597-11e6-930f-7494ee615827.png) + +### Changes +- :sparkles: The library now offers an elegant way to **convert from and to arbitrary value types**. All you need to do is to implement two functions: `to_json` and `from_json`. Then, a conversion is as simple as putting a `=` between variables. See the [README](https://github.com/nlohmann/json#arbitrary-types-conversions) for more information and examples. +- :sparkles: **Exceptions can now be switched off.** This can be done by defining the preprocessor symbol `JSON_NOEXCEPTION` or by passing `-fno-exceptions` to your compiler. In case the code would usually thrown an exception, `abort()` is now called. +- :sparkles: **Information on the library** can be queried with the new (static) function `meta()` which returns a JSON object with information on the version, compiler, and platform. See the [documentation]() for an example. +- :bug: A bug in the CBOR parser was fixed which led to a buffer overflow. +- :sparkles: The function [`type_name()`]() is now public. It allows to query the type of a JSON value as string. +- :white_check_mark: Added the [Big List of Naughty Strings](https://github.com/minimaxir/big-list-of-naughty-strings) as test case. +- :arrow_up: Updated to [Catch v1.6.0](https://github.com/philsquared/Catch/releases/tag/v1.6.0). +- :memo: Some typos in the documentation have been fixed. + + +## v2.0.10 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.10/json.hpp) (409 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.10/json.hpp.asc) (1 KB) + +- Release date: 2017-01-02 +- SHA-256: ec27d4e74e9ce0f78066389a70724afd07f10761009322dc020656704ad5296d + +### Summary + +This release fixes several security-relevant bugs in the MessagePack and CBOR parsers. The fixes are backwards compatible. + +### Changes +- :bug: Fixed a lot of **bugs in the CBOR and MesssagePack parsers**. These bugs occurred if invalid input was parsed and then could lead in buffer overflows. These bugs were found with Google's [OSS-Fuzz](https://github.com/google/oss-fuzz), see #405, #407, #408, #409, #411, and #412 for more information. +- :construction_worker: We now also use the **[Doozer](https://doozer.io) continuous integration platform**. +- :construction_worker: The complete test suite is now also run with **Clang's address sanitizer and undefined-behavior sanitizer**. +- :white_check_mark: Overworked **fuzz testing**; CBOR and MessagePack implementations are now fuzz-tested. Furthermore, all fuzz tests now include a round trip which ensures created output can again be properly parsed and yields the same JSON value. +- :memo: Clarified documentation of `find()` function to always return `end()` when called on non-object value types. +- :hammer: Moved thirdparty test code to `test/thirdparty` directory. + +## v2.0.9 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.9/json.hpp) (406 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.9/json.hpp.asc) (1 KB) + +- Release date: 2016-12-16 +- SHA-256: fbf3396f13e187d6c214c297bddc742d918ea9b55e10bfb3d9f458b9bfdc22e5 + +### Summary + +This release implements with **[CBOR](http://cbor.io)** and **[MessagePack](http://msgpack.org)** two **binary serialization/deserialization formats**. It further contains some small fixes and improvements. The fixes are backwards compatible. + +![cbor](https://cloud.githubusercontent.com/assets/159488/22399181/d4d60d32-e597-11e6-8dcb-825abcf9ac2a.png) + +### Changes +- :sparkles: The library can now read and write the binary formats **[CBOR](http://cbor.io)** (Concise Binary Object Representation) and **[MessagePack](http://msgpack.org)**. Both formats are aimed to produce a very compact representation of JSON which can be parsed very efficiently. See the [README file](https://github.com/nlohmann/json#binary-formats-cbor-and-messagepack) for more information and examples. +- :fire: simplified the iteration implementation allowing to remove dozens of lines of code +- :bug: fixed an [integer overflow error](https://github.com/nlohmann/json/issues/389) detected by [Google's OSS-Fuzz](https://github.com/google/oss-fuzz) +- :bug: suppressed documentation warnings inside the library to facilitate compilation with `-Wdocumentation` +- :bug: fixed an overflow detection error in the number parser +- :memo: updated [contribution guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md) to a list of frequentely asked features that will most likely be never added to the library +- :memo: added a **table of contents** to the [README file](https://github.com/nlohmann/json/blob/develop/README.md) to add some structure +- :memo: mentioned the many [examples](https://github.com/nlohmann/json/tree/develop/doc/examples) and the [documentation](https://nlohmann.github.io/json/) in the [README file]() +- :hammer: split [unit tests](https://github.com/nlohmann/json/tree/develop/test/src) into individual independent binaries to speed up compilation and testing +- :white_check_mark: the test suite now contains **11201886** tests + +## v2.0.8 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.8/json.hpp) (360 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.8/json.hpp.asc) (1 KB) + +- Release date: 2016-12-02 +- SHA-256: b70db0ad34f8e0e61dc3f0cbab88099336c9674c193d8a3439d93d6aca2d7120 + +### Summary + +This release combines a lot of small fixes and improvements. The fixes are backwards compatible. + +### Changes +- :bug: fixed a bug that froze the parser if a passed file was not found (now, `std::invalid_argument` is thrown) +- :bug: fixed a bug that lead to an error of a file at EOF was parsed again (now, `std::invalid_argument` is thrown) +- :sparkles: the well known functions [`emplace`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604) and [`emplace_back`](http://nlohmann.github.io/json/doxygen/classnlohmann_1_1basic__json_af8a435033327d9237da414afc1cce513.html#af8a435033327d9237da414afc1cce513) have been added to JSON values and work as expected +- :zap: improved the performance of the serialization (`dump` function) +- :zap: improved the performance of the deserialization (parser) +- :construction_worker: some continuous integration images at [Travis](https://travis-ci.org/nlohmann/json) were added and retired; see [here](https://github.com/nlohmann/json#supported-compilers) for the current continuous integration setup +- :construction_worker: the [Coverity scan](https://scan.coverity.com/projects/nlohmann-json) works again +- :chart_with_upwards_trend: the benchmarking code has been improved to produce more stable results +- :memo: the [README](https://github.com/nlohmann/json/blob/develop/README.md) file has been extended and includes more frequently asked examples +- :white_check_mark: the test suite now contains 8905518 tests +- :arrow_up: updated [Catch](https://github.com/philsquared/Catch) to version 1.5.8 + +## v2.0.7 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.7/json.hpp) (355 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.7/json.hpp.asc) (1 KB) + +- Release date: 2016-11-02 +- SHA-256: 5545c323670f8165bae90b9dc6078825e86ec310d96cc4e5b47233ea43715bbf + +### Summary + +This release fixes a few bugs in the JSON parser found in the [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.html) article. The fixes are backwards compatible. + +### Changes +- The article [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.html) discusses a lot of pitfalls of the JSON specification. When investigating the published test cases, a few bugs in the library were found and fixed: + - Files with less than 5 bytes can now be parsed without error. + - The library now properly rejects any file encoding other than UTF-8. Furthermore, incorrect surrogate pairs are properly detected and rejected. + - The library now accepts all but one "yes" test (y_string_utf16.json): UTF-16 is not supported. + - The library rejects all but one "no" test (n_number_then_00.json): Null bytes are treated as end of file instead of an error. This allows to parse input from null-terminated strings. +- The string length passed to a user-defined string literal is now exploited to choose a more efficient constructor. +- A few grammar mistakes in the README file have been fixed. + +## v2.0.6 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.6/json.hpp) (349 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.6/json.hpp.asc) (1 KB) + +- Release date: 2016-10-15 +- SHA256: 459cc93d5e2f503e50c6d5876eb86bfea7daf405f5a567c5a2c9abc2383756ae + +### Summary + +This release fixes the semantics of `operator[]` for JSON Pointers (see below). This fix is backwards compatible. + +### Changes +- **`operator[]` for JSON Pointers** now behaves like the other versions of `operator[]` and transforms `null` values into objects or arrays if required. This allows to created nested structues like `j["/foo/bar/2"] = 17` (yielding `{"foo": "bar": [null, null, 17]}`) without problems. +- overworked a helper SFINAE function +- fixed some documentation issues +- fixed the CMake files to allow to run the test suite outside the main project directory +- restored test coverage to 100%. + +## v2.0.5 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.5/json.hpp) (347 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.5/json.hpp.asc) (1 KB) + +- Release date: 2016-09-14 +- SHA-256: 8b7565263a44e2b7d3b89808bc73d2d639037ff0c1f379e3d56dbd77e00b98d9 + +### Summary + +This release fixes a regression bug in the stream parser (function `parse()` and the `<<`/`>>` operators). This fix is backwards compatible. + +### Changes +- **Bug fix**: The end of a file stream was not detected properly which led to parse errors. This bug should have been fixed with 2.0.4, but there was still a flaw in the code. + +## v2.0.4 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.4/json.hpp) (347 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.4/json.hpp.asc) (1 KB) + +- Release date: 2016-09-11 +- SHA-256: 632ceec4c25c4e2153f71470d3a2b992c8355f6d8b4d627d05dd16095cd3aeda + +### Summary + +This release fixes a bug in the stream parser (function `parse()` and the `<<`/`>>` operators). This fix is backwards compatible. + +### Changes +- **Bug fix**: The end of a file stream was not detected properly which led to parse errors. +- Fixed a compiler warning about an unused variable. + +## v2.0.3 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.3/json.hpp) (347 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.3/json.hpp.asc) (1 KB) + +- Release date: 2016-08-31 +- SHA-256: 535b73efe5546fde9e763c14aeadfc7b58183c0b3cd43c29741025aba6cf6bd3 + +### Summary + +This release combines a lot of small fixes and improvements. The release is backwards compatible. + +### Changes +- The **parser/deserialization functions have been generalized** to process any contiguous sequence of 1-byte elements (e.g., `char`, `unsigned char`, `uint8_t`). This includes all kind of string representations (string literals, char arrays, `std::string`, `const char*`), contiguous containers (C-style arrays, `std::vector`, `std::array`, `std::valarray`, `std::initializer_list`). User-defined containers providing random-access iterator access via `std::begin` and `std::end` can be used as well. See the documentation ([1](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_ace63ac4eb1dd7251a259d32e397461a3.html#ace63ac4eb1dd7251a259d32e397461a3), [2](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a90f05d55d9d0702c075cd281fd0d85ae.html#a90f05d55d9d0702c075cd281fd0d85ae), [3](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aeffd70f622f8f2a51fd3d95af64b63a7.html#aeffd70f622f8f2a51fd3d95af64b63a7), [4](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa8dca2e91a6301c36890f844e64f0023.html#aa8dca2e91a6301c36890f844e64f0023)) for more information. Note that contiguous storage cannot be checked at compile time; if any of the parse functions are called with a noncompliant container, the behavior is undefined and will most likely yield segmentation violation. The preconditions are enforced by an assertion unless the library is compiled with preprocessor symbol `NDEBUG`. +- As a general remark on **assertions**: The library uses assertions to preclude undefined behavior. A [prominent example](https://github.com/nlohmann/json/issues/289) for this is the `operator[]` for const JSON objects. The behavior of this const version of the operator is undefined if the given key does not exist in the JSON object, because unlike the non-const version, it cannot add a `null` value at the given key. Assertions can be switched of by defining the preprocessor symbol `NDEBUG`. See the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert) for more information. +- In the course of cleaning up the parser/deserialization functions, the constructor [`basic_json(std::istream&, const parser_callback_t)`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a32350263eb105764844c5a85e156a255.html#a32350263eb105764844c5a85e156a255) has been **deprecated** and will be deleted with the next major release 3.0.0 to unify the interface of the library. Deserialization will be done by stream operators or by calling one of the `parse` functions. That is, calls like `json j(i);` for an input stream `i` need to be replaced by `json j = json::parse(i);`. Compilers will produce a deprecation warning if client code uses this function. +- Minor improvements: + - Improved the performance of the serialization by avoiding the re-creation of a locale object. + - Fixed two MSVC warnings. Compiling the test suite with `/Wall` now only warns about non-inlined functions (C4710) and the deprecation of the constructor from input-stream (C4996). +- Some project internals: + - The project has qualified for the [Core Infrastructure Initiative Best Practices Badge](https://bestpractices.coreinfrastructure.org/projects/289). While most requirements where already satisfied, some led to a more explicit documentation of quality-ensuring procedures. For instance, static analysis is now executed with every commit on the build server. Furthermore, the [contribution guidelines document](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md) how to communicate security issues privately. + - The test suite has been overworked and split into several files to allow for faster compilation and analysis. The execute the test suite, simply execute `make check`. + - The continuous integration with [Travis](https://travis-ci.org/nlohmann/json) was extended with Clang versions 3.6.0 to 3.8.1 and now includes 18 different compiler/OS combinations. + - An 11-day run of [American fuzzy lop](http://lcamtuf.coredump.cx/afl/) checked 962 million inputs on the parser and found no issue. + +## v2.0.2 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.2/json.hpp) (338 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.2/json.hpp.asc) (1 KB) + +- Release date: 2016-07-31 +- SHA-256: 8e97b7965b4594b00998d6704465412360e1a0ed927badb51ded8b82291a8f3d + +### Summary + +This release combines a lot of small fixes and improvements. The release is backwards compatible. + +### Changes +- The **parser** has been overworked, and a lot of small issues have been fixed: + - Improved parser performance by avoiding recursion and using move semantics for the return value. + - Unescaped control charaters `\x10`-`\x1f` are not accepted any more. + - Fixed a bug in the parser when reading from an input stream. + - Improved test case coverage for UTF-8 parsing: now, all valid Unicode code points are tested both escaped and unescaped. + - The precision of output streams is now preserved by the parser. +- Started to check the **code correctness** by proving termination of important loops. Furthermore, individual assertions have been replaced by a more systematic function which checks the class invariants. Note that assertions should be switched off in production by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). +- A lot of **code cleanup**: removed unused headers, fixed some compiler warnings, and fixed a build error for Windows-based Clang builds. +- Added some compile-time checks: + - Unsupported compilers are rejected during compilation with an `#error` command. + - Static assertion prohibits code with incompatible pointer types used in `get_ptr()`. +- Improved the [documentation](https://nlohmann.github.io/json/), and adjusted the documentation script to choose the correct version of `sed`. +- Replaced a lot of "raw loops" by STL functions like `std::all_of`, `std::for_each`, or `std::accumulate`. This facilitates reasoning about termination of loops and sometimes allowed to simplify functions to a single return statement. +- Implemented a `value()` function for JSON pointers (similar to `at` function). +- The Homebrew formula (see [Integration](https://github.com/nlohmann/json#integration)) is now tested for all Xcode builds (6.1 - 8.x) with Travis. +- Avoided output to `std::cout` in the test cases. + +## v2.0.1 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.1/json.hpp) (321 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.1/json.hpp.asc) (1 KB) + +- Release date: 2016-06-28 +- SHA-256: ef550fcd7df572555bf068e9ec4e9d3b9e4cdd441cecb0dcea9ea7fd313f72dd + +### Summary + +This release fixes a performance regression in the JSON serialization (function `dump()`). This fix is backwards compatible. + +### Changes +- The locale of the output stream (or the internal string stream if a JSON value is serialized to a string) is now adjusted once for the whole serialization instead of for each floating-point number. +- The locale of an output stream is now correctly reset to the previous value by the JSON library. + + +## v2.0.0 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v2.0.0/json.hpp) (321 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v2.0.0/json.hpp.asc) (1 KB) + +- Release date: 2016-06-24 +- SHA-256: ac9e1fb25c2ac9ca5fc501fcd2fe3281fe04f07018a1b48820e7b1b11491bb6c + +### Summary + +This release adds several features such as JSON Pointers, JSON Patch, or support for 64 bit unsigned integers. Furthermore, several (subtle) bugs have been fixed. + +As `noexcept` and `constexpr` specifier have been added to several functions, the public API has effectively been changed in a (potential) non-backwards compatible manner. As we adhere to [Semantic Versioning](http://semver.org), this calls for a new major version, so say hello to 2️⃣.0️⃣.0️⃣. + +### Changes +- 🔟 A JSON value now uses `uint64_t` (default value for template parameter `NumberUnsignedType`) as data type for **unsigned integer** values. This type is used automatically when an unsigned number is parsed. Furthermore, constructors, conversion operators and an `is_number_unsigned()` test have been added. +- 👉 **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) support: A JSON Pointer is a string (similar to an XPath expression) to address a value inside a structured JSON value. JSON Pointers can be used in `at()` and `operator[]` functions. Furthermore, JSON values can be “flattened” to key/value pairs using `flatten()` where each key is a JSON Pointer. The original value can be restored by “unflattening” the flattened value using `unflatten()`. +- 🏥 **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) support. A JSON Patch is a JSON value that describes the required edit operations (add, change, remove, …) to transform a JSON value into another one. A JSON Patch can be created with function `diff(const basic_json&)` and applied with `patch(const basic_json&)`. Note the created patches use a rather primitive algorithm so far and leave room for improvement. +- 🇪🇺 The code is now **locale-independent**: Floating-point numbers are always serialized with a period (`.`) as decimal separator and ignores different settings from the locale. +- 🍺 **Homebrew** support: Install the library with `brew tap nlohmann/json && brew install nlohmann_json`. +- Added constructor to create a JSON value by parsing a `std::istream` (e.g., `std::stringstream` or `std::ifstream`). +- Added **`noexcept`** specifier to `basic_json(boolean_t)`, `basic_json(const number_integer_t)`, `basic_json(const int)`, `basic_json(const number_float_t)`, iterator functions (`begin()`, `end()`, etc.) +- When parsing numbers, the sign of `0.0` (vs. `-0.0`) is preserved. +- Improved MSVC 2015, Android, and MinGW support. See [README](https://github.com/nlohmann/json#supported-compilers) for more information. +- Improved test coverage (added 2,225,386 tests). +- Removed some misuses of `std::move`. +- Fixed several compiler warnings. +- Improved error messages from JSON parser. +- Updated to [`re2c`](http://re2c.org) to version 0.16 to use a minimal DFAs for the lexer. +- Updated test suite to use [Catch](https://github.com/philsquared/Catch) version 1.5.6. +- Made type getters (`is_number`, etc.) and const value access `constexpr`. +- Functions `push_back` and `operator+=` now work with key/value pairs passed as initializer list, e.g. `j_object += {"key", 1}`. +- Overworked `CMakeLists.txt` to make it easier to integrate the library into other projects. + +### Notes +- Parser error messages are still very vague and contain no information on the error location. +- The implemented `diff` function is rather primitive and does not create minimal diffs. +- The name of function `iteration_wrapper` may change in the future and the function will be deprecated in the next release. +- Roundtripping (i.e., parsing a JSON value from a string, serializing it, and comparing the strings) of floating-point numbers is not 100% accurate. Note that [RFC 7159](https://tools.ietf.org/html/rfc7159) defines no format to internally represent numbers and states not requirement for roundtripping. Nevertheless, benchmarks like [Native JSON Benchmark](https://github.com/miloyip/nativejson-benchmark) treat roundtripping deviations as conformance errors. + + +## v1.1.0 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v1.1.0/json.hpp) (257 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v1.1.0/json.hpp.asc) (1 KB) + +- Release date: 2016-01-24 +- SHA-256: c0cf0e3017798ca6bb18e757ebc570d21a3bdac877845e2b9e9573d183ed2f05 + +### Summary + +This release fixes several small bugs and adds functionality in a backwards-compatible manner. Compared to the [last version (1.0.0)](https://github.com/nlohmann/json/releases/tag/v1.0.0), the following changes have been made: + +### Changes +- _Fixed_: **Floating-point numbers** are now serialized and deserialized properly such that rountripping works in more cases. [#185, #186, #190, #191, #194] +- _Added_: The code now contains **assertions** to detect undefined behavior during development. As the standard function `assert` is used, the assertions can be switched off by defining the preprocessor symbol `NDEBUG` during compilation. [#168] +- _Added_: It is now possible to get a **reference** to the stored values via the newly added function `get_ref()`. [#128, #184] +- _Fixed_: Access to object values via keys (**`operator[]`**) now works with all kind of string representations. [#171, #189] +- _Fixed_: The code now compiles again with **Microsoft Visual Studio 2015**. [#144, #167, #188] +- _Fixed_: All required headers are now included. +- _Fixed_: Typos and other small issues. [#162, #166, #175, #177, #179, #180] + +### Notes + +There are still known open issues (#178, #187) which will be fixed in version 2.0.0. However, these fixes will require a small API change and will not be entirely backwards-compatible. + + +## v1.0.0 + +!!! summary "Files" + + - [json.hpp](https://github.com/nlohmann/json/releases/download/v1.0.0/json.hpp) (243 KB) + - [json.hpp.asc](https://github.com/nlohmann/json/releases/download/v1.0.0/json.hpp.asc) (1 KB) + +- Release date: 2015-12-28 +- SHA-256: 767dc2fab1819d7b9e19b6e456d61e38d21ef7182606ecf01516e3f5230446de + +### Summary + +This is the first official release. Compared to the [prerelease version 1.0.0-rc1](https://github.com/nlohmann/json/releases/tag/v1.0.0-rc1), only a few minor improvements have been made: + +### Changes +- _Changed_: A **UTF-8 byte order mark** is silently ignored. +- _Changed_: `sprintf` is no longer used. +- _Changed_: `iterator_wrapper` also works for const objects; note: the name may change! +- _Changed_: **Error messages** during deserialization have been improved. +- _Added_: The `parse` function now also works with type `std::istream&&`. +- _Added_: Function `value(key, default_value)` returns either a copy of an object's element at the specified key or a given default value if no element with the key exists. +- _Added_: Public functions are tagged with the version they were introduced. This shall allow for better **versioning** in the future. +- _Added_: All public functions and types are **documented** (see http://nlohmann.github.io/json/doxygen/) including executable examples. +- _Added_: Allocation of all types (in particular arrays, strings, and objects) is now exception-safe. +- _Added_: They descriptions of thrown exceptions have been overworked and are part of the tests suite and documentation. diff --git a/doc/mkdocs/docs/home/sponsors.md b/doc/mkdocs/docs/home/sponsors.md new file mode 100644 index 00000000..e2c5d91f --- /dev/null +++ b/doc/mkdocs/docs/home/sponsors.md @@ -0,0 +1,11 @@ +# Sponsors + +You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). + +## Named Sponsors + +- [Michael Hartmann](https://github.com/reFX-Mike) +- [Stefan Hagen](https://github.com/sthagen) +- [Steve Sperandeo](https://github.com/homer6) + +Thanks everyone! diff --git a/doc/mkdocs/docs/hooks.py b/doc/mkdocs/docs/hooks.py new file mode 100644 index 00000000..a04a7c53 --- /dev/null +++ b/doc/mkdocs/docs/hooks.py @@ -0,0 +1,7 @@ +import shutil +import os.path + + +def copy_doxygen(*args, **kwargs): + shutil.copytree('../html', os.path.join(kwargs['config']['site_dir'], 'doxygen')) + print('Copy Doxygen complete') diff --git a/doc/mkdocs/docs/index.md b/doc/mkdocs/docs/index.md new file mode 100644 index 00000000..9e5e54a4 --- /dev/null +++ b/doc/mkdocs/docs/index.md @@ -0,0 +1,7 @@ +# JSON for Modern C++ + +!!! note + + This page is under construction. You probably want to see the [Doxygen documentation](doxygen). + +![](images/json.gif) diff --git a/doc/mkdocs/docs/integration/cmake.md b/doc/mkdocs/docs/integration/cmake.md new file mode 100644 index 00000000..76f05dbe --- /dev/null +++ b/doc/mkdocs/docs/integration/cmake.md @@ -0,0 +1,103 @@ +# 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: + +```cmake +# CMakeLists.txt +find_package(nlohmann_json 3.2.0 REQUIRED) +... +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. + +## 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 "") + +# If you only include this third party in PRIVATE source files, you do not +# need to install it when your main project gets installed. +# set(JSON_Install OFF CACHE INTERNAL "") + +# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it +# unintended 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) +``` + +## Embedded (FetchContent) + +Since CMake v3.11, +[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can +be used to automatically download the repository as a dependency at configure type. + +Example: +```cmake +include(FetchContent) + +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.7.3) + +FetchContent_GetProperties(json) +if(NOT json_POPULATED) + FetchContent_Populate(json) + add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) +``` + +!!! Note + The repository download size is huge. + It contains all the dataset used for the benchmarks. You might want to depend on + a smaller repository. For instance, you might want to replace the URL above by + . + +## 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. diff --git a/doc/mkdocs/docs/integration/conan/CMakeLists.txt b/doc/mkdocs/docs/integration/conan/CMakeLists.txt new file mode 100644 index 00000000..fd3e9ca7 --- /dev/null +++ b/doc/mkdocs/docs/integration/conan/CMakeLists.txt @@ -0,0 +1,9 @@ +project(json_example) +cmake_minimum_required(VERSION 2.8.12) +add_definitions("-std=c++11") + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(json_example example.cpp) +target_link_libraries(json_example ${CONAN_LIBS}) diff --git a/doc/mkdocs/docs/integration/conan/Conanfile.txt b/doc/mkdocs/docs/integration/conan/Conanfile.txt new file mode 100644 index 00000000..a8a3e703 --- /dev/null +++ b/doc/mkdocs/docs/integration/conan/Conanfile.txt @@ -0,0 +1,5 @@ +[requires] +nlohmann_json/3.7.3 + +[generators] +cmake diff --git a/doc/mkdocs/docs/integration/conan/example.cpp b/doc/mkdocs/docs/integration/conan/example.cpp new file mode 100644 index 00000000..e5a31be4 --- /dev/null +++ b/doc/mkdocs/docs/integration/conan/example.cpp @@ -0,0 +1,9 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << json::meta() << std::endl; +} diff --git a/doc/mkdocs/docs/integration/example.cpp b/doc/mkdocs/docs/integration/example.cpp new file mode 100644 index 00000000..e5a31be4 --- /dev/null +++ b/doc/mkdocs/docs/integration/example.cpp @@ -0,0 +1,9 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << json::meta() << std::endl; +} diff --git a/doc/mkdocs/docs/integration/index.md b/doc/mkdocs/docs/integration/index.md new file mode 100644 index 00000000..5dd8cceb --- /dev/null +++ b/doc/mkdocs/docs/integration/index.md @@ -0,0 +1,14 @@ +# Integration + +[`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 + +```cpp +#include + +// for convenience +using json = nlohmann::json; +``` + +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). + +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`. diff --git a/doc/mkdocs/docs/integration/package_managers.md b/doc/mkdocs/docs/integration/package_managers.md new file mode 100644 index 00000000..17f2005e --- /dev/null +++ b/doc/mkdocs/docs/integration/package_managers.md @@ -0,0 +1,143 @@ +# Package Managers + +Throughout this page, we will describe how to compile the example file `example.cpp` below. + +```cpp +--8<-- "integration/example.cpp" +``` + +## Homebrew + +If you are using OS X and [Homebrew](http://brew.sh), just type + +```sh +brew tap nlohmann/json +brew install nlohmann_json +``` + +and you're set. If you want the bleeding edge rather than the latest release, use + +```sh +brew tap nlohmann/json +brew install nlohmann_json --HEAD +``` + +instead. + +!!! example + + 1. Create the following file: + + === "example.cpp" + + ```cpp + --8<-- "integration/example.cpp" + ``` + + 2. Install the package + + ```sh + brew tap nlohmann/json + brew install nlohmann_json + ``` + + 3. Determine the include path, which defaults to `/usr/local/Cellar/nlohmann_json/$version/include`, where `$version` is the version of the library, e.g. `3.7.3`. The path of the library can be determined with + + ```sh + brew list nlohmann_json + ``` + + 4. Compile the code. For instance, the code can be compiled using Clang with + + ```sh + clang++ example.cpp -I/usr/local/Cellar/nlohmann_json/3.7.3/include -std=c++11 -o example + ``` + +## Meson + +If you are using the [Meson Build System](http://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, 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`. Please see the meson project for any issues regarding the packaging. + +The provided meson.build can also be used as an alternative to cmake for installing `nlohmann_json` system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than using the subproject directly. + +## Conan + +If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `nlohmann_json/x.y.z` to your `conanfile`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/conan-io/conan-center-index/issues) if you experience problems with the packages. + +!!! example + + 1. Create the following files: + + === "Conanfile.txt" + + ```ini + --8<-- "integration/conan/Conanfile.txt" + ``` + + === "CMakeLists.txt" + + ```cmake + --8<-- "integration/conan/CMakeLists.txt" + ``` + + === "example.cpp" + + ```cpp + --8<-- "integration/conan/example.cpp" + ``` + + + 2. Build: + + ```sh + mkdir build + cd build + conan install .. + cmake .. + cmake --build . + ``` + +## Spack + +If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. + +## Hunter + +If you are using [hunter](https://github.com/cpp-pm/hunter) on your project for external dependencies, then you can use the [nlohmann_json package](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging. + +## Buckaroo + +If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. Please file issues [here](https://github.com/buckaroo-pm/nlohmann-json). There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example). + +## vcpkg + +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. + +## cget + +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`). + + +## CocoaPods + +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). + +## NuGet + +If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/). Please check [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) on how to use the package. Please files issues [here](https://github.com/hnkb/nlohmann-json-nuget/issues). + +## Conda + +If you are using [conda](https://conda.io/), you can use the package [nlohmann_json](https://github.com/conda-forge/nlohmann_json-feedstock) from [conda-forge](https://conda-forge.org) executing `conda install -c conda-forge nlohmann_json`. Please file issues [here](https://github.com/conda-forge/nlohmann_json-feedstock/issues). + +## MSYS2 + +If you are using [MSYS2](http://www.msys2.org/), your can use the [mingw-w64-nlohmann-json](https://packages.msys2.org/base/mingw-w64-nlohmann-json) package, just type `pacman -S mingw-w64-i686-nlohmann-json` or `pacman -S mingw-w64-x86_64-nlohmann-json` for installation. Please file issues [here](https://github.com/msys2/MINGW-packages/issues/new?title=%5Bnlohmann-json%5D) if you experience problems with the packages. + +## build2 + +If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository http://cppget.org or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). +Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages. + +## wsjcpp + +If you are using [`wsjcpp`](http://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch. diff --git a/doc/mkdocs/mkdocs.yml b/doc/mkdocs/mkdocs.yml new file mode 100644 index 00000000..5d6e3b4e --- /dev/null +++ b/doc/mkdocs/mkdocs.yml @@ -0,0 +1,120 @@ +# Project information +site_name: JSON for Modern C++ +site_author: Niels Lohmann +site_url: https://squidfunk.github.io/mkdocs-material/ + +# Repository +repo_name: nlohmann/json +repo_url: https://github.com/nlohmann/json +edit_uri: edit/develop/doc/mkdocs/docs + +# Copyright +copyright: Copyright © 2013 - 2020 Niels Lohmann + +# Configuration +theme: + name: material + language: en + palette: + primary: indigo + accent: indigo + font: + text: Roboto + code: Roboto Mono + features: + - tabs + - instant + +nav: + - Home: + - index.md + - home/license.md + - "Code of Conduct": home/code_of_conduct.md + - "FAQ": home/faq.md + - home/exceptions.md + - home/releases.md + - home/design_goals.md + - home/sponsors.md + - Features: + - features/arbitrary_types.md + - Binary Formats: + - features/binary_formats/index.md + - features/binary_formats/bson.md + - features/binary_formats/cbor.md + - features/binary_formats/messagepack.md + - features/binary_formats/ubjson.md + - features/binary_values.md + - features/iterators.md + - features/json_pointer.md + - features/json_patch.md + - features/merge_patch.md + - features/enum_conversion.md + - Parsing: + - features/parsing/index.md + - features/parsing/parse_exceptions.md + - features/parsing/parser_callbacks.md + - features/parsing/sax_interface.md + - features/types.md + - Integration: + - integration/index.md + - integration/cmake.md + - integration/package_managers.md + - Doxygen: + - doxygen/index.html + +# Extras +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/nlohmann + - icon: fontawesome/brands/twitter + link: https://twitter.com/nlohmann + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/nielslohmann/ + - icon: fontawesome/brands/xing + link: https://www.xing.com/profile/Niels_Lohmann + - icon: fontawesome/brands/paypal + link: https://www.paypal.me/nlohmann + +# Extensions +markdown_extensions: + - admonition + - codehilite: + guess_lang: false + - toc: + permalink: true + - pymdownx.arithmatex + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.critic + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.inlinehilite + - pymdownx.magiclink + - pymdownx.mark + #- pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tabbed + - pymdownx.tilde + - pymdownx.snippets: + base_path: docs + check_paths: true + - plantuml_markdown: + format: svg + +plugins: + - search: + separator: '[\s\-\.]+' + - mkdocs-simple-hooks: + hooks: + on_post_build: "docs.hooks:copy_doxygen" + - minify: + minify_html: true + +extra_javascript: + - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML diff --git a/doc/mkdocs/requirements.txt b/doc/mkdocs/requirements.txt new file mode 100644 index 00000000..b64e9b87 --- /dev/null +++ b/doc/mkdocs/requirements.txt @@ -0,0 +1,29 @@ +click>=7.1.2 +future>=0.18.2 +htmlmin>=0.1.12 +httplib2>=0.18.1 +importlib-metadata>=1.6.0 +Jinja2>=2.11.2 +joblib>=0.15.1 +jsmin>=2.2.2 +livereload>=2.6.1 +lunr>=0.5.8 +Markdown>=3.2.2 +markdown-include>=0.5.1 +MarkupSafe>=1.1.1 +mkdocs>=1.1.2 +mkdocs-material>=5.2.1 +mkdocs-material-extensions>=1.0 +mkdocs-minify-plugin>=0.3.0 +mkdocs-simple-hooks>=0.1.1 +nltk>=3.5 +plantuml>=0.3.0 +plantuml-markdown>=3.2.2 +Pygments>=2.6.1 +pymdown-extensions>=7.1 +PyYAML>=5.3.1 +regex>=2020.5.14 +six>=1.15.0 +tornado>=6.0.4 +tqdm>=4.46.0 +zipp>=3.1.0