Repository navigation
How to serialize a templated class explicitly WITHOUT the _TPL_ macros #699
|
How to serialize a templated class explicitly WITHOUT the TPL macros? I want the equivalent of Let's say I have a class |
Replies: 2 comments
|
For your sample class, the TPL_ macro, JSONCONS_TPL_ALL_GETTER_SETTER_TRAITS(1, Foo, , , bar)will generate a corresponding namespace jsoncons {
namespace reflect {
template <typename Json, typename T1 >
struct json_conv_traits<Json, Foo < T1 >>
{
using value_type = Foo < T1 >;
using result_type = conversion_result<value_type>;
static bool is(const Json& j) noexcept
{
if (!j.is_object()) return false;
if (!j.contains("bar")) return false;
return true;
}
template <typename Alloc, typename TempAlloc>
static result_type try_as(const allocator_set<Alloc, TempAlloc>& aset, const Json& j)
{
if (!j.is_object()) return result_type(jsoncons::unexpect, conv_errc::not_map, "Foo");
value_type value = jsoncons::make_obj_using_allocator<value_type>(aset.get_allocator());
auto it = j.find("bar");
if (it == j.object_range().end())
{
return result_type(jsoncons::unexpect, conv_errc::missing_required_member, "Foo::bar");
}
auto r = it->value().try_as<int>();
if (!r)
{
return result_type(jsoncons::unexpect, r.error().code(), "Foo::bar");
}
value.bar(std::move(*r));
return result_type(std::move(value));
}
template <typename Alloc, typename TempAlloc>
static Json to_json(const allocator_set<Alloc, TempAlloc>& aset, const value_type& value)
{
Json j = jsoncons::make_obj_using_allocator<Json>(aset.get_allocator(), json_object_arg, semantic_tag::none);
j.try_emplace("bar", value.bar());
return j;
}
};
} // namespace reflect
} // namespace jsonconsInternally, With the specialization of int main()
{
Foo<int> foo{};
foo.bar(10);
std::string buf;
jsoncons::encode_json_pretty(foo, buf);
std::cout << buf << "\n";
auto new_foo = jsoncons::decode_json<Foo<int>>(buf);
assert(new_foo.bar() == 10);
// json_conv_traits supports non-throwing error reporting
std::string bad_foo = R"({"baz" : 1})";
auto result = jsoncons::try_decode_json<Foo<int>>(bad_foo);
if (!result)
{
std::cout << result.error().message() << "\n";
}
} |
|
The simpler #include <jsoncons/json.hpp>
#include <iostream>
#include <cassert>
template<typename T>
class Foo {
public:
auto bar() const -> int {
return bar_;
}
void bar(int new_bar) {
bar_ = new_bar;
}
private:
int bar_;
};
namespace jsoncons {
template <typename Json, typename T1 >
struct json_type_traits<Json, Foo < T1 >>
{
using value_type = Foo < T1 >;
using result_type = conversion_result<value_type>;
using allocator_type = typename Json::allocator_type;
static bool is(const Json& ajson) noexcept
{
if (!ajson.is_object()) return false;
if (!ajson.contains("bar")) return false;
return true;
}
static result_type as(const Json& ajson)
{
if (!is(ajson))
{
JSONCONS_THROW(ser_error(conv_errc::not_map, "Not a Foo"));
}
value_type class_instance;
class_instance.bar(ajson.at("bar").as<int>());
return class_instance;
}
static Json to_json(const value_type& instance,
const allocator_type& = allocator_type{})
{
Json ajson{json_object_arg, semantic_tag::none};
ajson.try_emplace("bar", instance.bar());
return ajson;
}
};
} // namespace jsoncons
int main()
{
Foo<int> foo{};
foo.bar(10);
std::string buf;
jsoncons::encode_json_pretty(foo, buf);
std::cout << buf << "\n";
auto new_foo = jsoncons::decode_json<Foo<int>>(buf);
assert(new_foo.bar() == 10);
// json_conv_traits supports non-throwing error reporting
std::string bad_foo = R"({"baz" : 1})";
auto result = jsoncons::try_decode_json<Foo<int>>(bad_foo);
if (!result)
{
std::cout << result.error().message() << "\n";
}
}Output: |
For your sample class, the TPL_ macro,
will generate a corresponding
json_conv_traitsspecialization, which you can also provide yourself as