From 96b5c824963fc3d952606fc5d0d2acadaeae827f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 23 Oct 2026 12:00:39 +0200 Subject: [PATCH] 2.4.5: keep the inlined number cases in from_json(ArithmeticType&) (#5891) Calling get_number_value() from from_json(ArithmeticType&) made GetArray> 2.4x slower (it changes the inlining of the std::array conversion), so that overload keeps its own switch, with a comment. get_arithmetic_value() still uses the shared helper. Signed-off-by: Niels Lohmann --- .../nlohmann/detail/conversions/from_json.hpp | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 1b127a2ef..fd2361d81 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -437,17 +437,46 @@ template < typename BasicJsonType, typename ArithmeticType, int > = 0 > inline void from_json(const BasicJsonType& j, ArithmeticType& val) { - if (get_number_value(j, val)) + // the number cases repeat get_number_value() on purpose: calling it here + // changes the inlining of get() in the std::array conversion, which then + // runs 2.4x slower (GetArray benchmark, #5891); unlike get_arithmetic_value(), + // a boolean is accepted + switch (static_cast(j)) { - return; - } + case value_t::number_unsigned: + { + // never null: a basic_json whose number_unsigned_t is number_integer_t + // stores no number_unsigned values (#2573) + const auto* ptr = j.template get_ptr(); + JSON_ASSERT(ptr != nullptr); + val = static_cast(*ptr); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } - // unlike get_arithmetic_value(), a boolean is accepted here - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - throw_type_must_be("number", j); + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + throw_type_must_be("number", j); } - val = static_cast(*j.template get_ptr()); } template