26 #ifndef DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP
27 #define DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP
30 #include <unordered_map>
33 #include <type_traits>
35 #include "nlohmann/json.hpp"
42 template <
class BaseT>
43 using ToJsonFunc = void (*)(nlohmann::json &, BaseT
const&);
45 template <
class BaseT>
46 using ToJsonRegistry = std::map<std::type_index, ToJsonFunc<BaseT>>;
48 template <
class BaseT>
49 using FromJsonFunc = std::unique_ptr<BaseT>(*)(nlohmann::json
const&);
51 template <
class BaseT>
52 using FromJsonRegistry = std::map<std::string, FromJsonFunc<BaseT>>;
54 template <
class BaseT>
55 ToJsonRegistry<BaseT> & GetToJsonRegistry()
57 static ToJsonRegistry<BaseT> map;
61 template <
class BaseT>
62 FromJsonRegistry<BaseT> & GetFromJsonRegistry()
64 static FromJsonRegistry<BaseT> map;
68 template <
class BaseT,
class T>
69 void ToJsonFuncTemplate(nlohmann::json & j, BaseT
const& v)
71 static_assert(std::is_base_of_v<BaseT, T>);
72 j =
static_cast<T const&
>(v);
75 template <
class BaseT,
class T>
76 std::unique_ptr<BaseT> FromJsonFuncTemplate(nlohmann::json
const& j)
78 static_assert(std::is_base_of_v<BaseT, T>);
79 return std::make_unique<T>(j.get<T>());
83 template <
class BaseT>
86 static void to_json(nlohmann::json & j, BaseT
const& v)
88 auto const& registry = ::digitalcurling3::polymorphic_json::detail::GetToJsonRegistry<BaseT>();
89 auto it = registry.find(
typeid(v));
90 if (it != registry.end()) {
93 std::ostringstream buf;
94 buf <<
"polymorphic json: type \"" <<
typeid(v).name() <<
"\" is not registered to \"" <<
typeid(BaseT).name() <<
"\"";
95 throw std::runtime_error(buf.str());
100 template <
class BaseT>
101 struct Serializer<std::unique_ptr<BaseT>> {
103 static void to_json(nlohmann::json & j, std::unique_ptr<BaseT>
const& v)
106 Serializer<BaseT>::to_json(j, *v);
112 static void from_json(nlohmann::json
const& j, std::unique_ptr<BaseT> & v)
119 auto const name = j.at(
"type").get<std::string>();
120 auto const& registry = ::digitalcurling3::polymorphic_json::detail::GetFromJsonRegistry<BaseT>();
121 auto it = registry.find(name);
122 if (it != registry.end()) {
125 std::ostringstream buf;
126 buf <<
"polymorphic json: type name \"" << name <<
"\" is not registered to \"" <<
typeid(BaseT).name() <<
"\"";
127 throw std::runtime_error(buf.str());
141 template <
class BaseT,
class T>
144 static_assert(std::is_base_of_v<BaseT, T>);
145 ::digitalcurling3::polymorphic_json::detail::GetToJsonRegistry<BaseT>().emplace(
typeid(T), ::digitalcurling3::polymorphic_json::detail::ToJsonFuncTemplate<BaseT, T>);
146 ::digitalcurling3::polymorphic_json::detail::GetFromJsonRegistry<BaseT>().emplace(std::string(name), ::digitalcurling3::polymorphic_json::detail::FromJsonFuncTemplate<BaseT, T>);
152 #endif // DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP