From 8165707990e4895aa85b3c508d45eb1883411869 Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Thu, 15 Mar 2018 15:35:00 -0400 Subject: [PATCH 01/10] basic_json now supports getting many type of strings --- .../nlohmann/detail/conversions/from_json.hpp | 19 +++++++++++++++++++ include/nlohmann/detail/meta.hpp | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index eccc04f1..b066b2b4 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -70,6 +70,25 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) s = *j.template get_ptr(); } +template < + typename BasicJsonType, typename CompatibleStringType, + enable_if_t < + is_compatible_string_type::value and + not std::is_same::value and + std::is_constructible < + BasicJsonType, typename CompatibleStringType::value_type >::value, + int > = 0 > +void from_json(const BasicJsonType& j, CompatibleStringType& s) +{ + if (JSON_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + + s = *j.template get_ptr(); +} + template void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { diff --git a/include/nlohmann/detail/meta.hpp b/include/nlohmann/detail/meta.hpp index b251afb6..780efba8 100644 --- a/include/nlohmann/detail/meta.hpp +++ b/include/nlohmann/detail/meta.hpp @@ -120,6 +120,16 @@ struct is_compatible_object_type_impl std::is_constructible::value; }; +template +struct is_compatible_string_type_impl : std::false_type {}; + +template +struct is_compatible_string_type_impl +{ + static constexpr auto value = + std::is_same::value; +}; + template struct is_compatible_object_type { @@ -130,6 +140,15 @@ struct is_compatible_object_type typename BasicJsonType::object_t, CompatibleObjectType >::value; }; +template +struct is_compatible_string_type +{ + static auto constexpr value = is_compatible_string_type_impl < + conjunction>, + has_value_type>::value, + typename BasicJsonType::string_t, CompatibleStringType >::value; +}; + template struct is_basic_json_nested_type { From 2a5506ed98a195257fa16c0cf1cc632dfff368ce Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Fri, 16 Mar 2018 13:16:10 -0400 Subject: [PATCH 02/10] Amalgamated headers --- single_include/nlohmann/json.hpp | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6b6655af..10a50a58 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -353,6 +353,16 @@ struct is_compatible_object_type_impl std::is_constructible::value; }; +template +struct is_compatible_string_type_impl : std::false_type {}; + +template +struct is_compatible_string_type_impl +{ + static constexpr auto value = + std::is_same::value; +}; + template struct is_compatible_object_type { @@ -363,6 +373,15 @@ struct is_compatible_object_type typename BasicJsonType::object_t, CompatibleObjectType >::value; }; +template +struct is_compatible_string_type +{ + static auto constexpr value = is_compatible_string_type_impl < + conjunction>, + has_value_type>::value, + typename BasicJsonType::string_t, CompatibleStringType >::value; +}; + template struct is_basic_json_nested_type { @@ -977,6 +996,25 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) s = *j.template get_ptr(); } +template < + typename BasicJsonType, typename CompatibleStringType, + enable_if_t < + is_compatible_string_type::value and + not std::is_same::value and + std::is_constructible < + BasicJsonType, typename CompatibleStringType::value_type >::value, + int > = 0 > +void from_json(const BasicJsonType& j, CompatibleStringType& s) +{ + if (JSON_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + + s = *j.template get_ptr(); +} + template void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { From 53d8d57921630d9dbb7b8701cbeda724bfbc4850 Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Thu, 29 Mar 2018 01:03:36 -0400 Subject: [PATCH 03/10] Amalgamate single include --- single_include/nlohmann/json.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 10a50a58..498ba880 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1321,6 +1321,16 @@ struct external_constructor j.m_value = std::move(s); j.assert_invariant(); } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } }; template<> @@ -12470,9 +12480,6 @@ class basic_json not detail::is_basic_json::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value -#endif -#if defined(JSON_HAS_CPP_17) - and not std::is_same::value #endif , int >::type = 0 > operator ValueType() const From c78dbc366c818a9ae7358e13a52c2abe82bf98eb Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Thu, 29 Mar 2018 01:03:57 -0400 Subject: [PATCH 04/10] Added test for conversion to string_view --- test/src/unit-conversions.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index d67f5acb..0b4bd912 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -39,6 +39,10 @@ using nlohmann::json; #include #include +#if defined(JSON_HAS_CPP_17) +#include +#endif + TEST_CASE("value conversion") { SECTION("get an object (explicit)") @@ -292,6 +296,13 @@ TEST_CASE("value conversion") std::string s = j.get(); CHECK(json(s) == j); } +#if defined(JSON_HAS_CPP_17) + SECTION("std::string_view") + { + std::string_view s = j.get(); + CHECK(json(s) == j); + } +#endif SECTION("exception in case of a non-string type") { @@ -331,6 +342,14 @@ TEST_CASE("value conversion") CHECK(json(s) == j); } +#if defined(JSON_HAS_CPP_17) + SECTION("std::string_view") + { + std::string_view s = j; + CHECK(json(s) == j); + } +#endif + SECTION("std::string") { std::string s = j; From aaee18ce906dd92d3d4999312c049d083205034e Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Mon, 9 Apr 2018 11:15:33 -0400 Subject: [PATCH 05/10] Added test for string conversion with string_view --- test/src/unit-conversions.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 0b4bd912..b059087c 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -329,6 +329,34 @@ TEST_CASE("value conversion") CHECK_THROWS_WITH(json(json::value_t::number_float).get(), "[json.exception.type_error.302] type must be string, but is number"); } + +#if defined(JSON_HAS_CPP_17) + SECTION("exception in case of a non-string type using string_view") + { + CHECK_THROWS_AS(json(json::value_t::null).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::object).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::array).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::boolean).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_integer).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get(), json::type_error&); + CHECK_THROWS_AS(json(json::value_t::number_float).get(), json::type_error&); + + CHECK_THROWS_WITH(json(json::value_t::null).get(), + "[json.exception.type_error.302] type must be string, but is null"); + CHECK_THROWS_WITH(json(json::value_t::object).get(), + "[json.exception.type_error.302] type must be string, but is object"); + CHECK_THROWS_WITH(json(json::value_t::array).get(), + "[json.exception.type_error.302] type must be string, but is array"); + CHECK_THROWS_WITH(json(json::value_t::boolean).get(), + "[json.exception.type_error.302] type must be string, but is boolean"); + CHECK_THROWS_WITH(json(json::value_t::number_integer).get(), + "[json.exception.type_error.302] type must be string, but is number"); + CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get(), + "[json.exception.type_error.302] type must be string, but is number"); + CHECK_THROWS_WITH(json(json::value_t::number_float).get(), + "[json.exception.type_error.302] type must be string, but is number"); + } +#endif } SECTION("get a string (implicit)") From 714c5926803cbf790396fee5776a8d63fe566c9b Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Fri, 1 Jun 2018 14:22:57 -0400 Subject: [PATCH 06/10] Disabled implicit conversion to string_view on MSVC 15.13 and older --- include/nlohmann/json.hpp | 4 ++-- single_include/nlohmann/json.hpp | 13 +++---------- test/src/unit-conversions.cpp | 7 +++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 7ecf631f..38b31240 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -2821,9 +2821,9 @@ class basic_json not detail::is_basic_json::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value -#endif -#if defined(JSON_HAS_CPP_17) +#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1913 and not std::is_same::value +#endif #endif , int >::type = 0 > operator ValueType() const diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 498ba880..2c9c94fd 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1321,16 +1321,6 @@ struct external_constructor j.m_value = std::move(s); j.assert_invariant(); } - - template::value, - int> = 0> - static void construct(BasicJsonType& j, const CompatibleStringType& str) - { - j.m_type = value_t::string; - j.m_value.string = j.template create(str); - j.assert_invariant(); - } }; template<> @@ -12480,6 +12470,9 @@ class basic_json not detail::is_basic_json::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value +#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1913 + and not std::is_same::value +#endif #endif , int >::type = 0 > operator ValueType() const diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index b059087c..ef27ac6f 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -39,6 +39,13 @@ using nlohmann::json; #include #include +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + #if defined(JSON_HAS_CPP_17) #include #endif From 4778c02ab5e224cb463f27158b6cf1d79732acf4 Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Fri, 1 Jun 2018 14:42:25 -0400 Subject: [PATCH 07/10] Set MSVC version from 1514 and older --- include/nlohmann/json.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 38b31240..9fef16f1 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -2821,7 +2821,7 @@ class basic_json not detail::is_basic_json::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value -#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1913 +#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1914 and not std::is_same::value #endif #endif diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2c9c94fd..a886cc9e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -12470,7 +12470,7 @@ class basic_json not detail::is_basic_json::value #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value -#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1913 +#if defined(JSON_HAS_CPP_17) && _MSC_VER <= 1914 and not std::is_same::value #endif #endif From e0e7fa39e755fd1868267eb075c335f7c8a58eee Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Sun, 3 Jun 2018 23:49:13 -0400 Subject: [PATCH 08/10] Re-added external_constructor with string compatible types --- include/nlohmann/detail/conversions/to_json.hpp | 10 ++++++++++ single_include/nlohmann/json.hpp | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index ce2bc0aa..b147d077 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -51,6 +51,16 @@ struct external_constructor j.m_value = std::move(s); j.assert_invariant(); } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } }; template<> diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a886cc9e..630e4027 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1321,6 +1321,16 @@ struct external_constructor j.m_value = std::move(s); j.assert_invariant(); } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } }; template<> From 5676a2a0762ea3a657b2be02d8d9f851f05513a8 Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Sun, 3 Jun 2018 23:51:07 -0400 Subject: [PATCH 09/10] Aligned template declaration --- include/nlohmann/detail/conversions/to_json.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index b147d077..2d4449f4 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -53,8 +53,8 @@ struct external_constructor } template::value, - int> = 0> + enable_if_t::value, + int> = 0> static void construct(BasicJsonType& j, const CompatibleStringType& str) { j.m_type = value_t::string; From 7acd90b6517e34c2482366d4b960b2bedafdfa89 Mon Sep 17 00:00:00 2001 From: Guillaume Racicot Date: Mon, 4 Jun 2018 11:18:19 -0400 Subject: [PATCH 10/10] Fixed check for compatible string type --- include/nlohmann/detail/conversions/from_json.hpp | 4 +--- include/nlohmann/detail/meta.hpp | 3 ++- single_include/nlohmann/json.hpp | 7 +++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index b066b2b4..b71bb0ec 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -75,9 +75,7 @@ template < enable_if_t < is_compatible_string_type::value and not std::is_same::value and - std::is_constructible < - BasicJsonType, typename CompatibleStringType::value_type >::value, + CompatibleStringType>::value, int > = 0 > void from_json(const BasicJsonType& j, CompatibleStringType& s) { diff --git a/include/nlohmann/detail/meta.hpp b/include/nlohmann/detail/meta.hpp index 780efba8..50200304 100644 --- a/include/nlohmann/detail/meta.hpp +++ b/include/nlohmann/detail/meta.hpp @@ -127,7 +127,8 @@ template struct is_compatible_string_type_impl { static constexpr auto value = - std::is_same::value; + std::is_same::value and + std::is_constructible::value; }; template diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a886cc9e..555aa1de 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -360,7 +360,8 @@ template struct is_compatible_string_type_impl { static constexpr auto value = - std::is_same::value; + std::is_same::value and + std::is_constructible::value; }; template @@ -1001,9 +1002,7 @@ template < enable_if_t < is_compatible_string_type::value and not std::is_same::value and - std::is_constructible < - BasicJsonType, typename CompatibleStringType::value_type >::value, + CompatibleStringType>::value, int > = 0 > void from_json(const BasicJsonType& j, CompatibleStringType& s) {