mirror of
https://github.com/nlohmann/json.git
synced 2026-07-31 14:45:58 +00:00
Document BSON interoperability and subtype-less binary round trips (#5330)
- warn about BSON marker 0x11 interoperability in both directions - explain subtype-less binary normalization to subtype 0x00 - add a round-trip test for binary values without a subtype Signed-off-by: YingqiDuan <141370165+YingqiDuan@users.noreply.github.com>
This commit is contained in:
@@ -35,6 +35,19 @@ The library uses the following mapping from JSON values types to BSON types:
|
||||
The mapping is **incomplete**, since only JSON-objects (and things contained therein) can be serialized to BSON.
|
||||
Also, keys may not contain U+0000, since they are serialized a zero-terminated c-strings.
|
||||
|
||||
!!! warning "BSON type 0x11 interoperability"
|
||||
|
||||
The BSON specification defines type `0x11` as a Timestamp. This library uses marker `0x11` when serializing
|
||||
`number_unsigned` values in the range `9223372036854775808..18446744073709551615`. Other BSON implementations may
|
||||
therefore interpret these values as Timestamps instead of unsigned integers.
|
||||
|
||||
!!! info "Binary values without a subtype"
|
||||
|
||||
BSON requires every binary value to have a subtype. If a binary value has no subtype, this library serializes it
|
||||
with the generic subtype `0x00`. After deserialization, `has_subtype()` returns `true` and `subtype()` returns `0`.
|
||||
As a result, serializing and deserializing a JSON object containing such a value produces a different JSON object,
|
||||
even though the binary data is unchanged.
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
@@ -82,8 +95,8 @@ The library maps BSON record types to JSON value types as follows:
|
||||
|
||||
!!! note "Handling of BSON type 0x11"
|
||||
|
||||
BSON type 0x11 is used to represent uint64 numbers. This library treats these values purely as uint64 numbers
|
||||
and does not parse them into date-related formats.
|
||||
This library deserializes BSON type `0x11` (Timestamp) as a `number_unsigned` value. The 64-bit value is preserved,
|
||||
but the Timestamp type information is not.
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -529,6 +529,41 @@ TEST_CASE("BSON")
|
||||
CHECK(json::from_bson(result, true, false) == j);
|
||||
}
|
||||
|
||||
SECTION("non-empty object with binary member without subtype")
|
||||
{
|
||||
const size_t N = 10;
|
||||
const auto s = std::vector<std::uint8_t>(N, 'x');
|
||||
json const j =
|
||||
{
|
||||
{ "entry", json::binary(s) }
|
||||
};
|
||||
|
||||
CHECK(!j.at("entry").get_binary().has_subtype());
|
||||
|
||||
std::vector<std::uint8_t> const expected =
|
||||
{
|
||||
0x1B, 0x00, 0x00, 0x00, // size (little endian)
|
||||
0x05, // entry: binary
|
||||
'e', 'n', 't', 'r', 'y', '\x00',
|
||||
|
||||
0x0A, 0x00, 0x00, 0x00, // size of binary (little endian)
|
||||
0x00, // Generic binary subtype
|
||||
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
|
||||
|
||||
0x00 // end marker
|
||||
};
|
||||
|
||||
const auto result = json::to_bson(j);
|
||||
CHECK(result == expected);
|
||||
|
||||
// roundtrip adds the generic binary subtype
|
||||
const auto roundtrip = json::from_bson(result);
|
||||
CHECK(roundtrip != j);
|
||||
CHECK(roundtrip.at("entry").get_binary().has_subtype());
|
||||
CHECK(roundtrip.at("entry").get_binary().subtype() == 0);
|
||||
CHECK(json::from_bson(result, true, false) == roundtrip);
|
||||
}
|
||||
|
||||
SECTION("non-empty object with binary member with subtype")
|
||||
{
|
||||
// an MD5 hash
|
||||
|
||||
Reference in New Issue
Block a user