From fe7a90063de72865e020cb520615d8274a314a35 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 10 Oct 2026 13:24:20 +0200 Subject: [PATCH] Throw type_error.321 for discarded values in to_bon8 write_bon8_value silently skipped discarded values, but the array/object count marker still counted them, so [1, discarded] produced 82 91: a marker announcing two elements followed by one. Throw type_error.321 like the other binary writers do, at any nesting level. Signed-off-by: Niels Lohmann --- docs/mkdocs/docs/api/basic_json/to_bon8.md | 2 + docs/mkdocs/docs/home/exceptions.md | 2 +- .../nlohmann/detail/output/binary_writer.hpp | 6 ++- single_include/nlohmann/json.hpp | 6 ++- tests/src/unit-bon8.cpp | 51 ++++++++++++++++++- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/mkdocs/docs/api/basic_json/to_bon8.md b/docs/mkdocs/docs/api/basic_json/to_bon8.md index 2d58b2660..14cc085f6 100644 --- a/docs/mkdocs/docs/api/basic_json/to_bon8.md +++ b/docs/mkdocs/docs/api/basic_json/to_bon8.md @@ -41,6 +41,8 @@ With (2), the bytes written before the exception remain in the output adapter. above 9223372036854775807, which BON8 cannot represent - Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if `j` contains a string that is not valid UTF-8 +- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is + discarded; example: `"cannot serialize discarded value to BON8"` ## Complexity diff --git a/docs/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md index d6fdce37a..5f9ad60c6 100644 --- a/docs/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -810,7 +810,7 @@ does not list an enumerator and it is therefore converted like the first listed A discarded value (one created by [`parse()`](../api/basic_json/parse.md) with a callback that returns `false` for the value, or by default-constructing a [`basic_json`](../api/basic_json/index.md) with [`value_t::discarded`](../api/basic_json/value_t.md)) was passed to a binary serialization function, either directly or -nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, or BSON. +nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, BSON, or BON8. !!! failure "Example message" diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 212d2658f..ee76d7e1f 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -809,6 +809,8 @@ class binary_writer /*! @param[in] j JSON value to serialize + + @throw type_error.321 if @a j or a value nested in it is discarded */ void write_bon8(const BasicJsonType& j) { @@ -2570,6 +2572,8 @@ class binary_writer @param[in] j JSON value to serialize @param[in,out] string_open whether the output ends with a non-empty string that has not been terminated with 0xFF + + @throw type_error.321 if @a j or a value nested in it is discarded */ void write_bon8_value(const BasicJsonType& j, bool& string_open) { @@ -2678,7 +2682,7 @@ class binary_writer case value_t::discarded: default: - break; + throw_on_discarded(j, "BON8"); } } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 09f67bdc3..221d69c9a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22426,6 +22426,8 @@ class binary_writer /*! @param[in] j JSON value to serialize + + @throw type_error.321 if @a j or a value nested in it is discarded */ void write_bon8(const BasicJsonType& j) { @@ -24187,6 +24189,8 @@ class binary_writer @param[in] j JSON value to serialize @param[in,out] string_open whether the output ends with a non-empty string that has not been terminated with 0xFF + + @throw type_error.321 if @a j or a value nested in it is discarded */ void write_bon8_value(const BasicJsonType& j, bool& string_open) { @@ -24295,7 +24299,7 @@ class binary_writer case value_t::discarded: default: - break; + throw_on_discarded(j, "BON8"); } } diff --git a/tests/src/unit-bon8.cpp b/tests/src/unit-bon8.cpp index b1d82ca29..1e24d32d4 100644 --- a/tests/src/unit-bon8.cpp +++ b/tests/src/unit-bon8.cpp @@ -82,9 +82,56 @@ TEST_CASE("BON8") { SECTION("discarded") { - // discarded values are not serialized + // a discarded value cannot be serialized to BON8 const json j = json::value_t::discarded; - CHECK(json::to_bon8(j).empty()); + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] cannot serialize discarded value to BON8", json::type_error&); + } + + SECTION("discarded values nested in a container") + { + const json discarded = json::value_t::discarded; + + SECTION("in a small array") + { + const json j = {1, discarded}; +#if JSON_DIAGNOSTICS + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] (/1) cannot serialize discarded value to BON8", json::type_error&); +#else + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] cannot serialize discarded value to BON8", json::type_error&); +#endif + } + + SECTION("as a small object value") + { + json j; + j["a"] = discarded; +#if JSON_DIAGNOSTICS + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] (/a) cannot serialize discarded value to BON8", json::type_error&); +#else + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] cannot serialize discarded value to BON8", json::type_error&); +#endif + } + + SECTION("in a large array") + { + const json j = {1, 2, 3, 4, 5, discarded}; +#if JSON_DIAGNOSTICS + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] (/5) cannot serialize discarded value to BON8", json::type_error&); +#else + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] cannot serialize discarded value to BON8", json::type_error&); +#endif + } + + SECTION("as a large object value") + { + json j = {{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}}; + j["f"] = discarded; +#if JSON_DIAGNOSTICS + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] (/f) cannot serialize discarded value to BON8", json::type_error&); +#else + CHECK_THROWS_WITH_AS(json::to_bon8(j), "[json.exception.type_error.321] cannot serialize discarded value to BON8", json::type_error&); +#endif + } } SECTION("null")