#pragma once #include #include namespace clice::impl { template constexpr inline bool is_optional_v = false; template constexpr inline bool is_optional_v> = true; template constexpr inline bool is_vector_like_v = false; template constexpr inline bool is_vector_like_v> = true; template constexpr inline bool is_vector_like_v> = true; } // namespace clice::impl namespace clice { using nlohmann::json; template auto serialize(const Object& object) { if constexpr(std::is_fundamental_v || std::is_same_v || std::is_same_v) { return json(object); } else if constexpr(impl::is_vector_like_v) { return json(object); } else if constexpr(std::is_enum_v) { return static_cast>(object); } else { json json; for_each(object, [&json](std::string_view name, auto& member) { using Member = std::remove_cvref_t; if constexpr(impl::is_optional_v) { if(member.has_value()) { json.emplace(name, serialize(member.value())); } } else { json.emplace(name, serialize(member)); } }); return std::move(json); } } template Object deserialize(const json& json) { if constexpr(std::is_fundamental_v || std::is_same_v || std::is_same_v) { return json.get(); } else if constexpr(impl::is_vector_like_v) { return json.get(); } else if constexpr(std::is_enum_v) { return static_cast(json.get>()); } else { Object object; for_each(object, [&json](std::string_view name, auto& member) { using Member = std::remove_cvref_t; if constexpr(impl::is_optional_v) { if(json.contains(name)) { member = deserialize(json[name]); } } else { member = deserialize(json[name]); } }); return std::move(object); } } } // namespace clice