diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index efc5c5331d..aff4093c5d 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -177,7 +177,8 @@ class binary_writer case value_t::number_float: { - double valueD = j.m_value.number_float; + const auto valueD = j.m_value.number_float; + const float valueF = static_cast(valueD); if (std::isnan(valueD)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); @@ -189,8 +190,13 @@ class binary_writer oa->write_character(valueD > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - oa->write_character(get_cbor_float_prefix(valueD)); - write_number(valueD); + if(static_cast(valueF) == valueD) { + oa->write_character(get_cbor_float_prefix(valueF)); + write_number(valueF); + } else { + oa->write_character(get_cbor_float_prefix(valueD)); + write_number(valueD); + } } break; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ac44a99dd5..89e05a8116 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -12164,7 +12164,8 @@ class binary_writer case value_t::number_float: { - double valueD = j.m_value.number_float; + const auto valueD = j.m_value.number_float; + const float valueF = static_cast(valueD); if (std::isnan(valueD)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); @@ -12176,8 +12177,13 @@ class binary_writer oa->write_character(valueD > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - oa->write_character(get_cbor_float_prefix(valueD)); - write_number(valueD); + if(static_cast(valueF) == valueD) { + oa->write_character(get_cbor_float_prefix(valueF)); + write_number(valueF); + } else { + oa->write_character(get_cbor_float_prefix(valueD)); + write_number(valueD); + } } break; } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index c49899bb00..b9ee8bce5c 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -853,6 +853,20 @@ TEST_CASE("CBOR") CHECK(json::from_cbor(result, true, false) == j); } + SECTION("0.5") + { + double v = 0.5; + json j = v; + // its double-precision float binary value is + // {0xfb, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + // but to save memory, we can store it as single-precision float. + std::vector expected = {0xfa, 0x3f, 0x00, 0x00, 0x00}; + const auto result = json::to_cbor(j); + CHECK(result == expected); + // roundtrip + CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result) == v); + } } SECTION("half-precision float (edge cases)")