diff --git a/src/json.hpp b/src/json.hpp index 7c428002c..5c8bdaca3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -154,10 +154,10 @@ struct to_json_fn struct from_json_fn { - template - constexpr auto operator()(T&& val) const -> decltype(from_json(std::forward(val))) + template + constexpr auto operator()(Json const& from, T& to) const -> decltype(from_json(from, to)) { - return from_json(std::forward(val)); + return from_json(from, to); } }; diff --git a/test/src/unit-constructor3.cpp b/test/src/unit-constructor3.cpp index 912772f3d..3e025c154 100644 --- a/test/src/unit-constructor3.cpp +++ b/test/src/unit-constructor3.cpp @@ -58,6 +58,11 @@ public: explicit operator bool() const noexcept { return _val != nullptr; } T const &operator*() const { return *_val; } + optional_type& operator=(T const& t) + { + _val = std::make_shared(t); + return *this; + } private: std::shared_ptr _val; @@ -81,6 +86,33 @@ json to_json(bit_more_complex_type const& p) return json{{"a", to_json(p.a)}, {"b", to_json(p.b)}, {"c", p.c}}; } +void from_json(json const&j, empty_type& t) +{ + assert(j.empty()); + t = empty_type{}; +} + +void from_json(json const&j, pod_type& t) +{ + t = {j["a"].get(), j["b"].get(), j["c"].get()}; +} + +void from_json(json const&j, bit_more_complex_type& t) +{ + // relying on json_traits struct here.. + t = {j["a"].get(), j["b"].get(), + j["c"].get()}; +} + +template +void from_json(json const& j, optional_type& t) +{ + if (j.is_null()) + t = optional_type{}; + else + t = j.get(); +} + template json to_json(optional_type const& opt) { @@ -360,5 +392,64 @@ TEST_CASE("to_json free function", "[udt]") auto const j = nlohmann::to_json(o); CHECK(expected == j); } + + SECTION("from value") + { + udt::optional_type o{{42, 42, 42}}; + + auto const expected = json{{"a", 42}, {"b", 42}, {"c", 42}}; + auto const j = nlohmann::to_json(o); + CHECK(expected == j); + } + } +} + +TEST_CASE("from_json free function", "[udt]") +{ + SECTION("pod_type") + { + auto const expected = udt::pod_type{42, 42, 42}; + auto const j = json{{"a", 42}, {"b", 42}, {"c", 42}}; + + // i really dislike this output parameter + udt::pod_type p; + nlohmann::from_json(j, p); + CHECK(p == expected); + } + + SECTION("bit_more_complex_type") + { + auto const expected = + udt::bit_more_complex_type{{42, 42, 42}, {41, 41, 41}, "forty"}; + auto const j = json{{"a", {{"a", 42}, {"b", 42}, {"c", 42}}}, + {"b", {{"a", 41}, {"b", 41}, {"c", 41}}}, + {"c", "forty"}}; + udt::bit_more_complex_type p; + nlohmann::from_json(j, p); + CHECK(p == expected); + } + + SECTION("optional_type") + { + SECTION("from null") + { + udt::optional_type expected; + json j; + udt::optional_type o; + + nlohmann::from_json(j, o); + CHECK(expected == o); + } + + SECTION("from value") + { + udt::optional_type expected{{42, 42, 42}}; + auto const j = json{{"a", 42}, {"b", 42}, {"c", 42}}; + udt::optional_type o; + + nlohmann::from_json(j, o); + CHECK(expected == o); + } + } }