diff --git a/docs/examples/from_bjdata.cpp b/docs/examples/from_bjdata.cpp new file mode 100644 index 000000000..961164c29 --- /dev/null +++ b/docs/examples/from_bjdata.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create byte vector + std::vector v = {0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, + 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D + }; + + // deserialize it with BJData + json j = json::from_bjdata(v); + + // print the deserialized JSON value + std::cout << std::setw(2) << j << std::endl; +} diff --git a/docs/examples/from_bjdata.output b/docs/examples/from_bjdata.output new file mode 100644 index 000000000..259f63bd4 --- /dev/null +++ b/docs/examples/from_bjdata.output @@ -0,0 +1,4 @@ +{ + "compact": true, + "schema": 0 +} diff --git a/docs/examples/to_bjdata.cpp b/docs/examples/to_bjdata.cpp new file mode 100644 index 000000000..0bfe33323 --- /dev/null +++ b/docs/examples/to_bjdata.cpp @@ -0,0 +1,63 @@ +#include +#include +#include + +using json = nlohmann::json; + +// function to print BJData's diagnostic format +void print_byte(uint8_t byte) +{ + if (32 < byte and byte < 128) + { + std::cout << (char)byte; + } + else + { + std::cout << (int)byte; + } +} + +int main() +{ + // create a JSON value + json j = R"({"compact": true, "schema": false})"_json; + + // serialize it to BJData + std::vector v = json::to_bjdata(j); + + // print the vector content + for (auto& byte : v) + { + print_byte(byte); + } + std::cout << std::endl; + + // create an array of numbers + json array = {1, 2, 3, 4, 5, 6, 7, 8}; + + // serialize it to BJData using default representation + std::vector v_array = json::to_bjdata(array); + // serialize it to BJData using size optimization + std::vector v_array_size = json::to_bjdata(array, true); + // serialize it to BJData using type optimization + std::vector v_array_size_and_type = json::to_bjdata(array, true, true); + + // print the vector contents + for (auto& byte : v_array) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size_and_type) + { + print_byte(byte); + } + std::cout << std::endl; +} diff --git a/docs/examples/to_bjdata.output b/docs/examples/to_bjdata.output new file mode 100644 index 000000000..087980cb9 --- /dev/null +++ b/docs/examples/to_bjdata.output @@ -0,0 +1,4 @@ +{i7compactTi6schemaF} +[i1i2i3i4i5i6i7i8] +[#i8i1i2i3i4i5i6i7i8 +[$i#i812345678 diff --git a/docs/mkdocs/docs/api/basic_json/from_bjdata.md b/docs/mkdocs/docs/api/basic_json/from_bjdata.md index 2f8f1ca04..3c5eeb351 100644 --- a/docs/mkdocs/docs/api/basic_json/from_bjdata.md +++ b/docs/mkdocs/docs/api/basic_json/from_bjdata.md @@ -1,3 +1,93 @@ # nlohmann::basic_json::from_bjdata -TODO +```cpp +// (1) +template +static basic_json from_bjdata(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true); +// (2) +template +static basic_json from_bjdata(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true); +``` + +Deserializes a given input to a JSON value using the BJData (Binary JData) serialization format. + +1. Reads from a compatible input. +2. Reads from an iterator range. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Template parameters + +`InputType` +: A compatible input, for instance: + + - an `std::istream` object + - a `FILE` pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. + +`IteratorType` +: a compatible iterator type + +## Parameters + +`i` (in) +: an input in BJData format convertible to an input adapter + +`first` (in) +: iterator to start of the input + +`last` (in) +: iterator to end of the input + +`strict` (in) +: whether to expect the input to be consumed until EOF (`#!cpp true` by default) + +`allow_exceptions` (in) +: whether to throw exceptions in case of a parse error (optional, `#!cpp true` by default) + +## Return value + +deserialized JSON value; in case of a parse error and `allow_exceptions` set to `#!cpp false`, the return value will be +`value_t::discarded`. The latter can be checked with [`is_discarded`](is_discarded.md). + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Exceptions + +- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or + the end of file was not reached when `strict` was set to true +- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs +- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string could not be parsed + successfully + +## Complexity + +Linear in the size of the input. + +## Examples + +??? example + + The example shows the deserialization of a byte vector in BJData format to a JSON value. + + ```cpp + --8<-- "examples/from_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/to_bjdata.md b/docs/mkdocs/docs/api/basic_json/to_bjdata.md index 2cace544d..1ea850523 100644 --- a/docs/mkdocs/docs/api/basic_json/to_bjdata.md +++ b/docs/mkdocs/docs/api/basic_json/to_bjdata.md @@ -1,3 +1,70 @@ # nlohmann::basic_json::to_bjdata -TODO +```cpp +// (1) +static std::vector to_bjdata(const basic_json& j, + const bool use_size = false, + const bool use_type = false); + +// (2) +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +``` + +Serializes a given JSON value `j` to a byte vector using the BJData (Binary JData) serialization format. BJData +aims to be more compact than JSON itself, yet more efficient to parse. + +1. Returns a byte vector containing the BJData serialization. +2. Writes the BJData serialization to an output adapter. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Parameters + +`j` (in) +: JSON value to serialize + +`o` (in) +: output adapter to write serialization to + +`use_size` (in) +: whether to add size annotations to container types; optional, `#!cpp false` by default. + +`use_type` (in) +: whether to add type annotations to container types (must be combined with `#!cpp use_size = true`); optional, +`#!cpp false` by default. + +## Return value + +1. BJData serialization as byte vector +2. (none) + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Complexity + +Linear in the size of the JSON value `j`. + +## Examples + +??? example + + The example shows the serialization of a JSON value to a byte vector in BJData format. + + ```cpp + --8<-- "examples/to_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/to_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index aed4a1a01..fb0f5fc18 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -4403,29 +4403,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return res ? result : basic_json(value_t::discarded); } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bjdata(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bjdata(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bjdata(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /// @brief create a JSON value from an input in BSON format /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ template diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ad777c92c..56c93cbfd 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22473,29 +22473,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return res ? result : basic_json(value_t::discarded); } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bjdata(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bjdata(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bjdata(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /// @brief create a JSON value from an input in BSON format /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ template diff --git a/tests/src/unit-bjdata.cpp b/tests/src/unit-bjdata.cpp index bc6c52833..9276d38e4 100644 --- a/tests/src/unit-bjdata.cpp +++ b/tests/src/unit-bjdata.cpp @@ -3319,21 +3319,6 @@ TEST_CASE("BJData roundtrips" * doctest::skip()) CHECK(j1 == j2); } - { - INFO_WITH_TEMP(filename + ": uint8_t* and size"); - // parse JSON file - std::ifstream f_json(filename); - json j1 = json::parse(f_json); - - // parse BJData file - auto packed = utils::read_binary_file(filename + ".bjdata"); - json j2; - CHECK_NOTHROW(j2 = json::from_bjdata({packed.data(), packed.size()})); - - // compare parsed JSON values - CHECK(j1 == j2); - } - { INFO_WITH_TEMP(filename + ": output to output adapters"); // parse JSON file