diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 3c9fa9199..546cc57e7 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3492,25 +3492,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__object_t_key_type} */ - reference at(const typename object_t::key_type& key) + template < class KeyType, typename std::enable_if < +#if defined(JSON_HAS_CPP_17) + std::is_same::value || +#endif + std::is_convertible::value, int >::type = 0 > + reference at(const KeyType& key) { // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return set_parent(m_value.object->at(key)); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else + if (JSON_HEDLEY_UNLIKELY(is_object())) { JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } + + auto it = m_value.object->find(key); + if (it == m_value.object->end()) + { + JSON_THROW(out_of_range::create(403, "key '" + std::string(key) + "' not found", *this)); + } + return set_parent(it->second); } /*! @@ -3543,25 +3543,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec `at()`. It also demonstrates the different exceptions that can be thrown., at__object_t_key_type_const} */ - const_reference at(const typename object_t::key_type& key) const + template < class KeyType, typename std::enable_if < +#if defined(JSON_HAS_CPP_17) + std::is_same::value || +#endif + std::is_convertible::value, int >::type = 0 > + const_reference at(const KeyType& key) const { // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else + if (JSON_HEDLEY_UNLIKELY(is_object())) { JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } + + auto it = m_value.object->find(key); + if (it == m_value.object->end()) + { + JSON_THROW(out_of_range::create(403, "key '" + std::string(key) + "' not found", *this)); + } + return it->second; } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 282f33291..adfe95058 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20305,25 +20305,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__object_t_key_type} */ - reference at(const typename object_t::key_type& key) + template < class KeyType, typename std::enable_if < +#if defined(JSON_HAS_CPP_17) + std::is_same::value || +#endif + std::is_convertible::value, int >::type = 0 > + reference at(const KeyType& key) { // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return set_parent(m_value.object->at(key)); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else + if (JSON_HEDLEY_UNLIKELY(is_object())) { JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } + + auto it = m_value.object->find(key); + if (it == m_value.object->end()) + { + JSON_THROW(out_of_range::create(403, "key '" + std::string(key) + "' not found", *this)); + } + return set_parent(it->second); } /*! @@ -20356,25 +20356,25 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec `at()`. It also demonstrates the different exceptions that can be thrown., at__object_t_key_type_const} */ - const_reference at(const typename object_t::key_type& key) const + template < class KeyType, typename std::enable_if < +#if defined(JSON_HAS_CPP_17) + std::is_same::value || +#endif + std::is_convertible::value, int >::type = 0 > + const_reference at(const KeyType& key) const { // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); - } - } - else + if (JSON_HEDLEY_UNLIKELY(is_object())) { JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } + + auto it = m_value.object->find(key); + if (it == m_value.object->end()) + { + JSON_THROW(out_of_range::create(403, "key '" + std::string(key) + "' not found", *this)); + } + return it->second; } /*! diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 40b7ac9d6..d7916f559 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -32,6 +32,10 @@ SOFTWARE. #include using nlohmann::json; +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) + #define JSON_HAS_CPP_17 +#endif + TEST_CASE("element access 2") { SECTION("object") @@ -60,6 +64,26 @@ TEST_CASE("element access 2") CHECK(j_const.at("floating") == json(42.23)); CHECK(j_const.at("object") == json::object()); CHECK(j_const.at("array") == json({1, 2, 3})); + +#if defined(JSON_HAS_CPP_17) + CHECK(j.at(std::string_view("integer")) == json(1)); + CHECK(j.at(std::string_view("unsigned")) == json(1u)); + CHECK(j.at(std::string_view("boolean")) == json(true)); + CHECK(j.at(std::string_view("null")) == json(nullptr)); + CHECK(j.at(std::string_view("string")) == json("hello world")); + CHECK(j.at(std::string_view("floating")) == json(42.23)); + CHECK(j.at(std::string_view("object")) == json::object()); + CHECK(j.at(std::string_view("array")) == json({1, 2, 3})); + + CHECK(j_const.at(std::string_view("integer")) == json(1)); + CHECK(j_const.at(std::string_view("unsigned")) == json(1u)); + CHECK(j_const.at(std::string_view("boolean")) == json(true)); + CHECK(j_const.at(std::string_view("null")) == json(nullptr)); + CHECK(j_const.at(std::string_view("string")) == json("hello world")); + CHECK(j_const.at(std::string_view("floating")) == json(42.23)); + CHECK(j_const.at(std::string_view("object")) == json::object()); + CHECK(j_const.at(std::string_view("array")) == json({1, 2, 3})); +#endif } SECTION("access outside bounds") @@ -1107,3 +1131,7 @@ TEST_CASE("element access 2 (throwing tests)") } } #endif + +#ifdef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_17 +#endif