From c7e079cc98a6c5534e8d4a209dd0984e569d0625 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <mail@nlohmann.me>
Date: Tue, 30 Jun 2020 14:26:52 +0200
Subject: [PATCH] :ambulance: add specialization of get_to #2175

---
 include/nlohmann/json.hpp        | 12 ++++++++++++
 single_include/nlohmann/json.hpp | 12 ++++++++++++
 test/src/unit-udt_macro.cpp      | 28 +++++++++++++++++-----------
 3 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index ace649b6..00b7ce55 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -3019,6 +3019,18 @@ class basic_json
         return v;
     }
 
+    // specialization to allow to call get_to with a basic_json value
+    // see https://github.com/nlohmann/json/issues/2175
+    template<typename ValueType,
+             detail::enable_if_t <
+                 detail::is_basic_json<ValueType>::value,
+                 int> = 0>
+    ValueType & get_to(ValueType& v) const
+    {
+        v = *this;
+        return v;
+    }
+
     template <
         typename T, std::size_t N,
         typename Array = T (&)[N],
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 7ab24c84..9cba3069 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -18949,6 +18949,18 @@ class basic_json
         return v;
     }
 
+    // specialization to allow to call get_to with a basic_json value
+    // see https://github.com/nlohmann/json/issues/2175
+    template<typename ValueType,
+             detail::enable_if_t <
+                 detail::is_basic_json<ValueType>::value,
+                 int> = 0>
+    ValueType & get_to(ValueType& v) const
+    {
+        v = *this;
+        return v;
+    }
+
     template <
         typename T, std::size_t N,
         typename Array = T (&)[N],
diff --git a/test/src/unit-udt_macro.cpp b/test/src/unit-udt_macro.cpp
index ab2d3245..a45b2c50 100644
--- a/test/src/unit-udt_macro.cpp
+++ b/test/src/unit-udt_macro.cpp
@@ -41,20 +41,22 @@ class person_with_private_data
   private:
     std::string name;
     int age = 0;
+    json metadata;
 
   public:
     bool operator==(const person_with_private_data& rhs) const
     {
-        return std::tie(name, age) == std::tie(rhs.name, rhs.age);
+        return std::tie(name, age, metadata) == std::tie(rhs.name, rhs.age, rhs.metadata);
     }
 
     person_with_private_data() = default;
-    person_with_private_data(std::string name, int age)
+    person_with_private_data(std::string name, int age, json metadata)
         : name(std::move(name))
         , age(age)
+        , metadata(std::move(metadata))
     {}
 
-    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name);
+    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata);
 };
 
 class person_without_private_data_1
@@ -62,19 +64,21 @@ class person_without_private_data_1
   public:
     std::string name;
     int age = 0;
+    json metadata;
 
     bool operator==(const person_without_private_data_1& rhs) const
     {
-        return std::tie(name, age) == std::tie(rhs.name, rhs.age);
+        return std::tie(name, age, metadata) == std::tie(rhs.name, rhs.age, rhs.metadata);
     }
 
     person_without_private_data_1() = default;
-    person_without_private_data_1(std::string name, int age)
+    person_without_private_data_1(std::string name, int age, json metadata)
         : name(std::move(name))
         , age(age)
+        , metadata(std::move(metadata))
     {}
 
-    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_without_private_data_1, age, name);
+    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_without_private_data_1, age, name, metadata);
 };
 
 class person_without_private_data_2
@@ -82,20 +86,22 @@ class person_without_private_data_2
   public:
     std::string name;
     int age = 0;
+    json metadata;
 
     bool operator==(const person_without_private_data_2& rhs) const
     {
-        return std::tie(name, age) == std::tie(rhs.name, rhs.age);
+        return std::tie(name, age, metadata) == std::tie(rhs.name, rhs.age, rhs.metadata);
     }
 
     person_without_private_data_2() = default;
-    person_without_private_data_2(std::string name, int age)
+    person_without_private_data_2(std::string name, int age, json metadata)
         : name(std::move(name))
         , age(age)
+        , metadata(std::move(metadata))
     {}
 };
 
-NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name);
+NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata);
 } // namespace persons
 
 TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE", T,
@@ -106,8 +112,8 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU
     SECTION("person")
     {
         // serialization
-        T p1("Erik", 1);
-        CHECK(json(p1).dump() == "{\"age\":1,\"name\":\"Erik\"}");
+        T p1("Erik", 1, {{"haircuts", 2}});
+        CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}");
 
         // deserialization
         T p2 = json(p1);