mirror of
https://github.com/nlohmann/json.git
synced 2026-10-04 05:30:31 +00:00
Round-trip BJData ND-array annotations exactly (single precision, key order)
to_bjdata() encoded a JData-annotated object as a BJData ND-array in two cases where from_bjdata() then returned a different value, breaking the documented round-trip guarantee: 1. A "single" element that is finite and in range but not exactly representable as float (e.g. 0.1) or that underflows to 0 (e.g. 1e-300) was silently narrowed instead of falling back to a plain object, unlike out-of-range integer elements. write_bjdata_ndarray() now only accepts a "single" element if it survives the narrowing to float and back, the same criterion write_compact_float() already uses for CBOR/MessagePack. 2. from_bjdata() emitted the annotation keys as _ArraySize_, _ArrayType_, _ArrayData_ instead of the documented _ArrayType_, _ArraySize_, _ArrayData_, because the size key is written while the dimension vector is read, before the type key. For ordered_json, whose comparison takes key order into account, this made a round trip of the documented example compare unequal. The element type marker is known before the dimension vector is read (it precedes '#'), so it is now passed down and the "_ArrayType_" key is emitted first. Fixes #5661. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -1991,9 +1991,21 @@ class binary_writer
|
||||
case 'd':
|
||||
{
|
||||
const auto dval = el.template get<double>();
|
||||
in_range = !std::isfinite(dval) ||
|
||||
#ifdef __GNUC__
|
||||
JSON_HEDLEY_DIAGNOSTIC_PUSH
|
||||
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
|
||||
#endif
|
||||
// a value that would be rounded (rather than exactly represented) by the
|
||||
// narrowing to float is treated like an out-of-range integer element above;
|
||||
// this is the same criterion write_compact_float() uses for CBOR/MessagePack
|
||||
in_range = std::isnan(dval) ||
|
||||
(dval >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
||||
dval <= static_cast<double>((std::numeric_limits<float>::max)()));
|
||||
dval <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
||||
static_cast<double>(static_cast<float>(dval)) == dval) ||
|
||||
std::isinf(dval);
|
||||
#ifdef __GNUC__
|
||||
JSON_HEDLEY_DIAGNOSTIC_POP
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user