diff --git a/doc/examples/operatorarray__key_type_const.cpp b/doc/examples/operatorarray__key_type_const.cpp
index 6d0c9141..a59cca58 100644
--- a/doc/examples/operatorarray__key_type_const.cpp
+++ b/doc/examples/operatorarray__key_type_const.cpp
@@ -5,7 +5,7 @@ using namespace nlohmann;
int main()
{
// create a JSON object
- json object =
+ const json object =
{
{"one", 1}, {"two", 2}, {"three", 2.9}
};
diff --git a/doc/examples/operatorarray__key_type_const.link b/doc/examples/operatorarray__key_type_const.link
index 0f03498a..7e740a1b 100644
--- a/doc/examples/operatorarray__key_type_const.link
+++ b/doc/examples/operatorarray__key_type_const.link
@@ -1 +1 @@
-online
\ No newline at end of file
+online
\ No newline at end of file
diff --git a/src/json.hpp b/src/json.hpp
index 6bfb44bf..e11bae2d 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -2862,6 +2862,45 @@ class basic_json
}
}
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @throw std::domain_error if JSON is not an object
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the [] operator.,operatorarray__key_type_const}
+
+ @sa @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa @ref value() for access by value with a default value
+
+ @since version 1.0
+ */
+ const_reference operator[](const typename object_t::key_type& key) const
+ {
+ // [] only works for objects
+ if (is_object())
+ {
+ return m_value.object->find(key)->second;
+ }
+ else
+ {
+ throw std::domain_error("cannot use operator[] with " + type_name());
+ }
+ }
+
/*!
@brief access specified object element
@@ -2911,6 +2950,48 @@ class basic_json
}
}
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @note This function is required for compatibility reasons with Clang.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @throw std::domain_error if JSON is not an object
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the [] operator.,operatorarray__key_type_const}
+
+ @sa @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa @ref value() for access by value with a default value
+
+ @since version 1.0
+ */
+ template
+ const_reference operator[](const T (&key)[n]) const
+ {
+ // at only works for objects
+ if (is_object())
+ {
+ return m_value.object->find(key)->second;
+ }
+ else
+ {
+ throw std::domain_error("cannot use operator[] with " + type_name());
+ }
+ }
+
/*!
@brief access specified object element with default value
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 3ab1dfce..119ec5c2 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -2862,6 +2862,45 @@ class basic_json
}
}
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @throw std::domain_error if JSON is not an object
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the [] operator.,operatorarray__key_type_const}
+
+ @sa @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa @ref value() for access by value with a default value
+
+ @since version 1.0
+ */
+ const_reference operator[](const typename object_t::key_type& key) const
+ {
+ // [] only works for objects
+ if (is_object())
+ {
+ return m_value.object->find(key)->second;
+ }
+ else
+ {
+ throw std::domain_error("cannot use operator[] with " + type_name());
+ }
+ }
+
/*!
@brief access specified object element
@@ -2911,6 +2950,48 @@ class basic_json
}
}
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @note This function is required for compatibility reasons with Clang.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @throw std::domain_error if JSON is not an object
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the [] operator.,operatorarray__key_type_const}
+
+ @sa @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa @ref value() for access by value with a default value
+
+ @since version 1.0
+ */
+ template
+ const_reference operator[](const T (&key)[n]) const
+ {
+ // at only works for objects
+ if (is_object())
+ {
+ return m_value.object->find(key)->second;
+ }
+ else
+ {
+ throw std::domain_error("cannot use operator[] with " + type_name());
+ }
+ }
+
/*!
@brief access specified object element with default value
diff --git a/test/unit.cpp b/test/unit.cpp
index b143f31b..e52128ce 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -3211,6 +3211,27 @@ TEST_CASE("element access")
CHECK(j["array"] == json({1, 2, 3}));
CHECK(j[json::object_t::key_type("array")] == j["array"]);
+
+ CHECK(j_const["integer"] == json(1));
+ CHECK(j_const[json::object_t::key_type("integer")] == j["integer"]);
+
+ CHECK(j_const["boolean"] == json(true));
+ CHECK(j_const[json::object_t::key_type("boolean")] == j["boolean"]);
+
+ CHECK(j_const["null"] == json(nullptr));
+ CHECK(j_const[json::object_t::key_type("null")] == j["null"]);
+
+ CHECK(j_const["string"] == json("hello world"));
+ CHECK(j_const[json::object_t::key_type("string")] == j["string"]);
+
+ CHECK(j_const["floating"] == json(42.23));
+ CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
+
+ CHECK(j_const["object"] == json(json::object()));
+ CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
+
+ CHECK(j_const["array"] == json({1, 2, 3}));
+ CHECK(j_const[json::object_t::key_type("array")] == j["array"]);
}
SECTION("access on non-object type")
@@ -3222,6 +3243,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_NOTHROW(j_nonobject["foo"]);
CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
SECTION("boolean")
@@ -3230,6 +3253,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
SECTION("string")
@@ -3238,6 +3263,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
SECTION("array")
@@ -3246,6 +3273,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
SECTION("number (integer)")
@@ -3254,6 +3283,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
SECTION("number (floating-point)")
@@ -3262,6 +3293,8 @@ TEST_CASE("element access")
const json j_const_nonobject(j_nonobject);
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
+ CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
}
}
}