Fix to_bjdata() emitting the Draft-3-only 'B' marker in default Draft-2 mode (#5479)

* Fix to_bjdata() emitting the Draft-3-only 'B' marker in default Draft-2 mode

_ArrayType_ = "byte" mapped unconditionally to the BJData type marker
'B', regardless of the requested bjdata_version. 'B' is defined only by
BJData Draft 3; with the default version (draft2), this produced a
stream that is invalid for Draft 2 and, unlike every other
_ArrayType_, round-tripped back as a binary value instead of the
original annotated object.

Only accept "byte" / emit 'B' when bjdata_version selects Draft 3.
Under Draft 2, fall back to the same plain-object encoding used
elsewhere in this function for other invalid-annotation cases, so the
value round-trips correctly.

Fixes #5404.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Future-proof the Draft-3-only 'B' marker gate

@gregmarr pointed out that dtype == 'B' && bjdata_version != draft3
only future-proofs by accident, since bjdata_version_t currently has
exactly two values. Compare with < instead, so a later draft that
keeps the 'B' marker valid does not need this gate revisited.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-16 20:20:21 +02:00
committed by GitHub
parent e8e1ba0db9
commit 502e9d66f6
3 changed files with 67 additions and 2 deletions
@@ -1707,6 +1707,16 @@ class binary_writer
}
CharType dtype = it->second;
// the 'B' (byte) marker is only defined from BJData Draft 3 onward;
// emitting it under an earlier draft would produce a stream that an
// earlier-draft reader rejects, so such an object falls back to a
// plain object encoding instead (see the "Binary values" section of
// the BJData documentation)
if (dtype == 'B' && bjdata_version < bjdata_version_t::draft3)
{
return true;
}
key = "_ArraySize_";
// the dimensions are written verbatim as the header length below, so a
// value that is not an array cannot produce a valid one: null emits 'Z'