diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 140cd8ab..f4049bd3 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -157,17 +157,21 @@ class binary_reader return success; } - void parse_bson_entries() + void parse_bson_entries(bool is_array) { while (auto entry_type = get()) { + string_t key; + get_bson_cstr(key); + if (!is_array) + { + sax->key(key); + } + switch (entry_type) { case 0x01: // double { - string_t key; - get_bson_cstr(key); - sax->key(key); double number; get_number_little_endian(number); sax->number_float(static_cast(number), ""); @@ -175,9 +179,6 @@ class binary_reader break; case 0x02: // string { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int32_t len; string_t value; get_number_little_endian(len); @@ -188,17 +189,11 @@ class binary_reader break; case 0x08: // boolean { - string_t key; - get_bson_cstr(key); - sax->key(key); sax->boolean(static_cast(get())); } break; case 0x10: // int32 { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int32_t value; get_number_little_endian(value); sax->number_integer(static_cast(value)); @@ -206,9 +201,6 @@ class binary_reader break; case 0x12: // int64 { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int64_t value; get_number_little_endian(value); sax->number_integer(static_cast(value)); @@ -216,25 +208,16 @@ class binary_reader break; case 0x0A: // null { - string_t key; - get_bson_cstr(key); - sax->key(key); sax->null(); } break; case 0x03: // object { - string_t key; - get_bson_cstr(key); - sax->key(key); parse_bson_internal(); } break; case 0x04: // array { - string_t key; - get_bson_cstr(key); - sax->key(key); parse_bson_array(); } break; @@ -252,7 +235,7 @@ class binary_reader return false; } - parse_bson_entries(); + parse_bson_entries(/*is_array*/true); const auto result = sax->end_array(); @@ -269,7 +252,7 @@ class binary_reader return false; } - parse_bson_entries(); + parse_bson_entries(/*is_array*/false); const auto result = sax->end_object(); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index adb0d294..6f481a8f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -6141,17 +6141,21 @@ class binary_reader return success; } - void parse_bson_entries() + void parse_bson_entries(bool is_array) { while (auto entry_type = get()) { + string_t key; + get_bson_cstr(key); + if (!is_array) + { + sax->key(key); + } + switch (entry_type) { case 0x01: // double { - string_t key; - get_bson_cstr(key); - sax->key(key); double number; get_number_little_endian(number); sax->number_float(static_cast(number), ""); @@ -6159,9 +6163,6 @@ class binary_reader break; case 0x02: // string { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int32_t len; string_t value; get_number_little_endian(len); @@ -6172,17 +6173,11 @@ class binary_reader break; case 0x08: // boolean { - string_t key; - get_bson_cstr(key); - sax->key(key); sax->boolean(static_cast(get())); } break; case 0x10: // int32 { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int32_t value; get_number_little_endian(value); sax->number_integer(static_cast(value)); @@ -6190,9 +6185,6 @@ class binary_reader break; case 0x12: // int64 { - string_t key; - get_bson_cstr(key); - sax->key(key); std::int64_t value; get_number_little_endian(value); sax->number_integer(static_cast(value)); @@ -6200,25 +6192,16 @@ class binary_reader break; case 0x0A: // null { - string_t key; - get_bson_cstr(key); - sax->key(key); sax->null(); } break; case 0x03: // object { - string_t key; - get_bson_cstr(key); - sax->key(key); parse_bson_internal(); } break; case 0x04: // array { - string_t key; - get_bson_cstr(key); - sax->key(key); parse_bson_array(); } break; @@ -6236,7 +6219,7 @@ class binary_reader return false; } - parse_bson_entries(); + parse_bson_entries(/*is_array*/true); const auto result = sax->end_array(); @@ -6253,7 +6236,7 @@ class binary_reader return false; } - parse_bson_entries(); + parse_bson_entries(/*is_array*/false); const auto result = sax->end_object(); diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index b2886110..fcaf51d6 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -408,6 +408,41 @@ TEST_CASE("BSON") CHECK(json::from_bson(result, true, false) == j); } + SECTION("non-empty object with non-empty array member") + { + json j = + { + { "entry", json::array({1, 2, 3, 4, 5, 6, 7, 8}) } + }; + + std::vector expected = + { + 0x41, 0x00, 0x00, 0x00, // size (little endian) + 0x04, /// entry: embedded document + 'e', 'n', 't', 'r', 'y', '\x00', + + 0x35, 0x00, 0x00, 0x00, // size (little endian) + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, // end marker (embedded document) + + 0x00 // end marker + }; + + const auto result = json::to_bson(j); + CHECK(result == expected); + + // roundtrip + CHECK(json::from_bson(result) == j); + CHECK(json::from_bson(result, true, false) == j); + } + SECTION("Some more complex document") { // directly encoding uint64 is not supported in bson (only for timestamp values)