From 03ccb5917e1e57845c8f964e2bf0765a8a7d0f80 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 1 Jan 2016 13:35:21 -0800 Subject: [PATCH] Abstract object/array type out so that arbitrary types can be used As suggested by @palacaze in #161, this allows using an unordered_map as well as anything that obeys the template type for the object type or template for the array type. --- src/json.hpp | 46 ++++++++++++++++++++++++---------------------- test/unit.cpp | 16 +++++++++++++++- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index c9fe4ebc5..9ae20531f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -107,6 +107,12 @@ static bool approx(const T a, const T b) } } +template +using default_object_type = std::map; + +template +using default_array_type = std::vector; + /*! @brief a class to store JSON values @@ -176,8 +182,8 @@ default) @nosubgrouping */ template < - template class ObjectType = std::map, - template class ArrayType = std::vector, + template class ObjectType = default_object_type, + template class ArrayType = default_array_type, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = int64_t, @@ -333,11 +339,7 @@ class basic_json @since version 1.0.0 */ - using object_t = ObjectType, - AllocatorType>>; + using object_t = ObjectType; /*! @brief a type for an array @@ -383,7 +385,7 @@ class basic_json @since version 1.0.0 */ - using array_t = ArrayType>; + using array_t = ArrayType; /*! @brief a type for a string @@ -959,7 +961,7 @@ class basic_json */ template ::value and + std::is_constructible::value and std::is_constructible::value, int>::type = 0> basic_json(const CompatibleObjectType& val) @@ -2159,7 +2161,7 @@ class basic_json /// get an object (explicit) template ::value and + std::is_convertible::value and std::is_convertible::value , int>::type = 0> T get_impl(T*) const @@ -2707,7 +2709,7 @@ class basic_json @since version 1.0.0 */ - reference at(const typename object_t::key_type& key) + reference at(const StringType& key) { // at only works for objects if (is_object()) @@ -2754,7 +2756,7 @@ class basic_json @since version 1.0.0 */ - const_reference at(const typename object_t::key_type& key) const + const_reference at(const StringType& key) const { // at only works for objects if (is_object()) @@ -2884,7 +2886,7 @@ class basic_json @since version 1.0.0 */ - reference operator[](const typename object_t::key_type& key) + reference operator[](const StringType& key) { // implicitly convert null to object if (is_null()) @@ -2931,7 +2933,7 @@ class basic_json @since version 1.0.0 */ - const_reference operator[](const typename object_t::key_type& key) const + const_reference operator[](const StringType& key) const { // [] only works for objects if (is_object()) @@ -3089,7 +3091,7 @@ class basic_json std::enable_if< std::is_convertible::value , int>::type = 0> - ValueType value(const typename object_t::key_type& key, ValueType default_value) const + ValueType value(const StringType& key, ValueType default_value) const { // at only works for objects if (is_object()) @@ -3115,7 +3117,7 @@ class basic_json @brief overload for a default value of type const char* @copydoc basic_json::value() */ - string_t value(const typename object_t::key_type& key, const char* default_value) const + string_t value(const StringType& key, const char* default_value) const { return value(key, string_t(default_value)); } @@ -3425,7 +3427,7 @@ class basic_json @since version 1.0.0 */ - size_type erase(const typename object_t::key_type& key) + size_type erase(const StringType& key) { // this erase only works for objects if (is_object()) @@ -3497,7 +3499,7 @@ class basic_json @since version 1.0.0 */ - iterator find(typename object_t::key_type key) + iterator find(StringType key) { auto result = end(); @@ -3513,7 +3515,7 @@ class basic_json @brief find an element in a JSON object @copydoc find(typename object_t::key_type) */ - const_iterator find(typename object_t::key_type key) const + const_iterator find(StringType key) const { auto result = cend(); @@ -3543,7 +3545,7 @@ class basic_json @since version 1.0.0 */ - size_type count(typename object_t::key_type key) const + size_type count(StringType key) const { // return 0 for all nonobject types return is_object() ? m_value.object->count(key) : 0; @@ -4176,7 +4178,7 @@ class basic_json @since version 1.0.0 */ - void push_back(const typename object_t::value_type& val) + void push_back(const std::pair& val) { // push_back only works for null objects or objects if (not(is_null() or is_object())) @@ -4199,7 +4201,7 @@ class basic_json @brief add an object to an object @copydoc push_back(const typename object_t::value_type&) */ - reference operator+=(const typename object_t::value_type& val) + reference operator+=(const std::pair& val) { push_back(val); return operator[](val.first); diff --git a/test/unit.cpp b/test/unit.cpp index ebf3fb2a3..c6fe61de8 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -11043,6 +11043,9 @@ TEST_CASE("RFC 7159 examples") } } +template +using unordered_map_type = std::unordered_map; + TEST_CASE("Unicode", "[hide]") { SECTION("full enumeration of Unicode codepoints") @@ -11216,7 +11219,13 @@ TEST_CASE("regression tests") SECTION("issue #89 - nonstandard integer type") { // create JSON class with nonstandard integer number type - nlohmann::basic_json j; + nlohmann::basic_json< + nlohmann::default_object_type, + nlohmann::default_array_type, + std::string, + bool, + int32_t, + float> j; j["int_1"] = 1; // we need to cast to int to compile with Catch - the value is int32_t CHECK(static_cast(j["int_1"]) == 1); @@ -11314,6 +11323,11 @@ TEST_CASE("regression tests") CHECK(s2 == "value"); } + SECTION("issue #164 - std::unordered_map cannot be used as Object Type") + { + nlohmann::basic_json unordered_json; + } + SECTION("character following a surrogate pair is skipped") { CHECK(json::parse("\"\\ud80c\\udc60abc\"").get() == u8"\U00013060abc");