diff --git a/include/json.hpp b/include/json.hpp index cdb0b63..e8737e4 100644 --- a/include/json.hpp +++ b/include/json.hpp @@ -2773,6 +2773,49 @@ static constexpr string_t unescape_string(const string_t& str) return result; } + +namespace _jsonization_helper +{ + struct required_tag + { + constexpr static bool required = true; + }; + struct optional_tag + { + constexpr static bool required = false; + }; +} + +struct bind_helper +{ + void __to_json(json::object&) const {} + + bool __from_json(const json::object&) { return true; } + + template + void __to_json(json::object& obj, Tag, const Var& var, const char* name, Rest&&... rest) const + { + obj[name] = json::serialize(var); + __to_json(obj, std::forward(rest)...); + } + + template + bool __from_json(const json::object& raw, Tag, Var& var, const char* name, Rest&&... rest) + { + if (auto opt = raw.find(name)) { + if (!opt->is()) { + return false; + } + var = std::move(opt)->as(); + } else { + if constexpr (Tag::required) { + return false; + } + } + return __from_json(raw, std::forward(rest)...); + } +}; + } // namespace json namespace json::_jsonization_helper @@ -2917,3 +2960,16 @@ namespace json::_private_macro } #define MEO_OPTIONAL json::_jsonization_helper::next_is_optional(), +#define MEO_REQ(var) json::_jsonization_helper::required_tag {}, var, #var +#define MEO_OPT(var) json::_jsonization_helper::optional_tag {}, var, #var +#define MEO_JSONBIND(...) \ + json::object to_json() const \ + { \ + json::object res; \ + bind_helper::__to_json(res, __VA_ARGS__); \ + return res; \ + } \ + bool from_json(const json::object& raw) \ + { \ + return bind_helper::__from_json(raw, __VA_ARGS__); \ + } diff --git a/sample/sample.cpp b/sample/sample.cpp index 73f48d2..da7e8ff 100644 --- a/sample/sample.cpp +++ b/sample/sample.cpp @@ -299,7 +299,7 @@ bool serializing() void test_jsonization() { - struct MyStruct + struct MyStruct : json::bind_helper { std::vector vec; std::map map; @@ -308,6 +308,7 @@ void test_jsonization() double d = 0; MEO_JSONIZATION(vec, map, MEO_OPTIONAL i, MEO_OPTIONAL d); + MEO_JSONBIND(MEO_REQ(vec), MEO_REQ(map), MEO_OPT(i), MEO_OPT(d)) }; MyStruct a; @@ -316,15 +317,29 @@ void test_jsonization() a.i = 100; a.d = 0.5; - json::object j = a.dump_to_json(); - std::cout << j << std::endl; + // json::object j = a.dump_to_json(); + // std::cout << j << std::endl; - // for test MEO_OPTIONAL - j.erase("i"); + // // for test MEO_OPTIONAL + // j.erase("i"); - MyStruct b; - bool loaded = b.load_from_json(j); + // MyStruct b; + // bool loaded = b.load_from_json(j); - std::cout << "loaded: " << loaded << std::endl; - std::cout << b.dump_to_json() << std::endl; + // std::cout << "loaded: " << loaded << std::endl; + // std::cout << b.dump_to_json() << std::endl; + + { + json::object j = a.to_json(); + std::cout << j << std::endl; + + // for test MEO_OPTIONAL + j.erase("i"); + + MyStruct b; + bool loaded = b.from_json(j); + + std::cout << "loaded: " << loaded << std::endl; + std::cout << b.to_json() << std::endl; + } }