From 2bc685f6b4ae2f53d80eaf526a073244c060a80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= <delrieutheo@gmail.com> Date: Wed, 9 Nov 2016 23:55:03 +0100 Subject: [PATCH] to_json and from_json takes both two arguments now the first is the basic_json type, the second the user-defined type --- src/json.hpp | 49 +++++++++++++++++++------------------------ test/src/unit-udt.cpp | 35 +++++++++++++++++-------------- 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index bd59e83b..4f471070 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -155,22 +155,21 @@ void from_json(); struct to_json_fn { - template <typename T> + template <typename Json, typename T> constexpr auto - operator()(T &&val) const noexcept(noexcept(to_json(std::forward<T>(val)))) - -> decltype(to_json(std::forward<T>(val))) + operator()(Json&& j, T &&val) const noexcept(noexcept(to_json(std::forward<Json>(j), std::forward<T>(val)))) + -> decltype(to_json(std::forward<Json>(j), std::forward<T>(val)), void()) { - return to_json(std::forward<T>(val)); + return to_json(std::forward<Json>(j), std::forward<T>(val)); } - }; struct from_json_fn { - template <typename T, typename Json> + template <typename Json, typename T> constexpr auto operator()(Json &&j, T &val) const noexcept(noexcept(from_json(std::forward<Json>(j), val))) - -> decltype(from_json(std::forward<Json>(j), val)) + -> decltype(from_json(std::forward<Json>(j), val), void()) { return from_json(std::forward<Json>(j), val); } @@ -219,28 +218,19 @@ inline namespace template <typename = void, typename = void> struct adl_serializer { - template <typename T, typename Json, typename = enable_if_t<std::is_default_constructible<uncvref_t<T>>::value>> - static auto from_json(Json&& j) -> uncvref_t<decltype(::nlohmann::from_json(std::forward<Json>(j), std::declval<T&>()), std::declval<T>())> - { - uncvref_t<T> ret; - ::nlohmann::from_json(std::forward<Json>(j), ret); - return ret; - } - - template <typename T, typename Json> - static auto from_json(Json&& j, T& val) -> decltype(::nlohmann::from_json(std::forward<Json>(j), val)) + template <typename Json, typename T> + static auto from_json(Json&& j, T& val) -> decltype(::nlohmann::from_json(std::forward<Json>(j), val), void()) { ::nlohmann::from_json(std::forward<Json>(j), val); } - template <typename T> - static auto to_json(T&& val) -> decltype(::nlohmann::to_json(std::forward<T>(val))) + template <typename Json, typename T> + static auto to_json(Json& j, T&& val) -> decltype(::nlohmann::to_json(j, std::forward<T>(val)), void()) { - return ::nlohmann::to_json(std::forward<T>(val)); + ::nlohmann::to_json(j, std::forward<T>(val)); } }; - /*! @brief a class to store JSON values @@ -1399,9 +1389,11 @@ class basic_json } // constructor chosen when JSONSerializer::to_json exists for type T - template <typename T, typename = decltype(JSONSerializer<uncvref_t<T>>::to_json(std::declval<uncvref_t<T>>()))> + template <typename T, typename = decltype(JSONSerializer<uncvref_t<T>>::to_json(std::declval<basic_json&>(), std::declval<uncvref_t<T>>()))> explicit basic_json(T &&val) - : basic_json(JSONSerializer<uncvref_t<T>>::to_json(std::forward<T>(val))) {} + { + JSONSerializer<uncvref_t<T>>::to_json(*this, std::forward<T>(val)); + } /*! @brief create a string (explicit) @@ -3072,11 +3064,14 @@ class basic_json return get_impl(static_cast<ValueType*>(nullptr)); } - template <typename ValueType, typename = enable_if_t<std::is_default_constructible<uncvref_t<ValueType>>::value, float>> - auto get() const -> remove_reference_t<decltype(JSONSerializer<uncvref_t<ValueType>>::from_json(*this, std::declval<ValueType&>()), std::declval<ValueType>())> + template <typename ValueType, typename = decltype(JSONSerializer<uncvref_t<ValueType>>::from_json(std::declval<basic_json>(), std::declval<ValueType&>()))> + auto get() const -> uncvref_t<ValueType> { - uncvref_t<ValueType> ret; - JSONSerializer<uncvref_t<ValueType>>::from_json(*this, ret); + using type = uncvref_t<ValueType>; + static_assert(std::is_default_constructible<type>::value && std::is_copy_constructible<type>::value, + "user-defined types must be DefaultConstructible and CopyConstructible when used with get"); + type ret; + JSONSerializer<type>::from_json(*this, ret); return ret; } diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 77b31c6a..17494a45 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -70,32 +70,31 @@ private: // free to/from_json functions -json to_json(empty_type) +void to_json(json& j, empty_type) { - return json::object(); + j = json::object(); } -json to_json(pod_type const& p) +void to_json(json& j, pod_type const& p) { - return {{"a", p.a}, {"b", p.b}, {"c", p.c}}; + j = json{{"a", p.a}, {"b", p.b}, {"c", p.c}}; } -json to_json(bit_more_complex_type const& p) +void to_json(json& j, bit_more_complex_type const& p) { - using nlohmann::to_json; - return json{{"a", to_json(p.a)}, {"b", to_json(p.b)}, {"c", p.c}}; + j = json{{"a", json(p.a)}, {"b", json(p.b)}, {"c", p.c}}; } template <typename T> -json to_json(optional_type<T> const& opt) +void to_json(json& j, optional_type<T> const& opt) { - using nlohmann::to_json; if (!opt) - return nullptr; - return json(*opt); + j = nullptr; + else + j = json(*opt); } -void from_json(json const&j, empty_type& t) +void from_json(json const& j, empty_type& t) { assert(j.empty()); t = empty_type{}; @@ -292,7 +291,8 @@ TEST_CASE("to_json free function", "[udt]") auto const e = udt::pod_type{42, 42, 42}; auto const expected = json{{"a", 42}, {"b", 42}, {"c", 42}}; - auto const j = nlohmann::to_json(e); + json j; + nlohmann::to_json(j, e); CHECK(j == expected); } @@ -303,7 +303,8 @@ TEST_CASE("to_json free function", "[udt]") auto const expected = json{{"a", {{"a", 42}, {"b", 42}, {"c", 42}}}, {"b", {{"a", 41}, {"b", 41}, {"c", 41}}}, {"c", "forty"}}; - auto const j = nlohmann::to_json(e); + json j; + nlohmann::to_json(j, e); CHECK(j == expected); } @@ -314,7 +315,8 @@ TEST_CASE("to_json free function", "[udt]") udt::optional_type<udt::pod_type> o; json expected; - auto const j = nlohmann::to_json(o); + json j; + nlohmann::to_json(j, o); CHECK(expected == j); } @@ -323,7 +325,8 @@ TEST_CASE("to_json free function", "[udt]") udt::optional_type<udt::pod_type> o{{42, 42, 42}}; auto const expected = json{{"a", 42}, {"b", 42}, {"c", 42}}; - auto const j = nlohmann::to_json(o); + json j; + nlohmann::to_json(j, o); CHECK(expected == j); } }