-
Notifications
You must be signed in to change notification settings - Fork 7
ObjectJson
JSON-описание сериализации структур данных:
template<typename T, typename L>
struct object
{
typedef T target;
typedef implementation_defined serializer;
typedef implementation_defined member_list;
};-
T - сериализуемый тип (
structилиclass) -
L - JSON-описание полей (список) сериализуемого типа
wjson::member_list
member_list - это псевдоним для списка типов faslib. Для c++03 ограничение до 26 элементов (но можно использовать вложения, без ограничений):
template<typename ...Args>
using member_list = typename fas::type_list_n<Args...>::type;JSON-описание поля структуры:
template<typename N, typename T, typename M, M T::* m, typename J = value<M> >
struct member;- N - имя поля
- T - тип структуры данных (можно использовать базовый класс)
- M - тип поля
- m - указатель на поле структуры
- J - JSON-описание для сериализации поля
Для передачи имени поля в шаблон, используется специальный тип, который можно создать с помощью макросов:
- JSON_NAME(name) - создаст тип
n_nameсо строкой "name" - JSON_NAME2(name, "name") - создаст тип
nameсо строкой "name"
Макрос раскрывается примерно в такую конструкцию:
struct n_name { const char* operator()() const { return "name"} };Пример для простой структуры:
struct foo
{
bool flag = false;
int value = 0;
std::string string;
};
JSON_NAME(flag)
JSON_NAME(value)
JSON_NAME(string)
typedef wjson::object<
foo,
wjson::member_list<
wjson::member<n_flag, foo, bool, &foo::flag>,
wjson::member<n_value, foo, int, &foo::value>,
wjson::member<n_string, foo, std::string, &foo::string>
>
> foo_json;
int main()
{
std::string json="{\"flag\":false,\"value\":0,\"string\":\"Привет Мир\"}";
foo f;
foo_json::serializer()( f, json.begin(), json.end(), nullptr );
f.flag = true;
f.string = "Пока Мир";
std::cout << json << std::endl;
foo_json::serializer()( f, std::ostream_iterator<char>(std::cout) );
return 0;
}Вывод:
{"flag":false,"value":0,"string":"Привет Мир"}
{"flag":true,"value":0,"string":"Пока Мир"}Для сериализации с наследованием можно использовать конструкцию base, либо внедрять в список поля базового класса. Типы bar_json и bar2_json в примере ниже эквивалентны.
#include <wjson/json.hpp>
#include <wjson/strerror.hpp>
#include <iostream>
struct foo
{
bool flag = false;
int value = 0;
std::string string;
};
struct bar: foo
{
std::vector<int> data;
};
JSON_NAME(flag)
JSON_NAME(value)
JSON_NAME(string)
typedef wjson::object<
foo,
wjson::member_list<
wjson::member<n_flag, foo, bool, &foo::flag>,
wjson::member<n_value, foo, int, &foo::value>,
wjson::member<n_string, foo,std::string, &foo::string>
>
> foo_json;
JSON_NAME(data)
typedef ::wjson::array< std::vector< ::wjson::value<int> > > vint_json;
typedef wjson::object<
bar,
wjson::member_list<
wjson::base<foo_json>,
wjson::member<n_data, bar, std::vector<int>, &bar::data, vint_json>
>
> bar_json;
typedef wjson::object<
bar,
wjson::member_list<
wjson::member<n_flag, foo, bool, &foo::flag>,
wjson::member<n_value, foo, int, &foo::value>,
wjson::member<n_string, foo, std::string, &foo::string>,
wjson::member<n_data, bar, std::vector<int>, &bar::data, vint_json>
>
> bar2_json;
int main()
{
std::string json="{\"flag\":false,\"value\":0,\"string\":\"Привет Мир\",\"data\":[1,2]";
bar b;
bar_json::serializer()( b, json.begin(), json.end(), nullptr );
b.flag = true;
b.data.push_back(3);
std::cout << json << std::endl;
bar2_json::serializer()(b, std::ostream_iterator<char>(std::cout) );
std::cout << std::endl;
}Вывод:
{"flag":false,"value":0,"string":"Привет Мир","data":[1,2]
{"flag":true,"value":0,"string":"Привет Мир","data":[1,2,3]}Для сериализации структуры в JSON-массив с фиксированным порядком значений элементов:
template<typename T, typename L>
struct object_array;-
T - сериализуемый тип (
structилиclass) -
L - JSON-описание полей (список) сериализуемого типа
wjson::member_list
Для описания членов структуры можно использовать wjson::member или аналогичную конструкцию, но без указания имени поля:
template<typename N, typename T, typename M, M T::* m, typename J = value<M> >
struct member_array;- T - тип структуры данных (можно использовать базовый класс)
- M - тип поля
- m - указатель на поле структуры
- J - JSON-описание для сериализации поля
Пример:
#include <wjson/json.hpp>
#include <wjson/strerror.hpp>
#include <iostream>
struct foo
{
bool flag = false;
int value = 0;
std::string string;
};
struct bar: foo
{
std::shared_ptr<foo> pfoo;
std::vector<foo> vfoo;
};
struct foo_json
{
JSON_NAME(flag)
JSON_NAME(value)
JSON_NAME(string)
typedef wjson::object_array<
foo,
wjson::member_list<
wjson::member<n_flag, foo,bool, &foo::flag>,
wjson::member<n_value, foo,int, &foo::value>,
wjson::member<n_string, foo,std::string, &foo::string>
>
> type;
typedef type::serializer serializer;
typedef type::target target;
typedef type::member_list member_list;
};
struct bar_json
{
typedef ::wjson::array< std::vector< foo_json > > vfoo_json;
typedef ::wjson::pointer< std::shared_ptr<foo>, foo_json > pfoo_json;
typedef wjson::object_array<
bar,
wjson::member_list<
wjson::base<foo_json>,
wjson::member_array<bar, std::vector<foo>, &bar::vfoo, vfoo_json>,
wjson::member_array<bar, std::shared_ptr<foo>, &bar::pfoo, pfoo_json>
>
> type;
typedef type::serializer serializer;
typedef type::target target;
typedef type::member_list member_list;
};
int main()
{
std::string json="[true,0,\"Привет Мир\",[],\"pfoo\":null]";
bar b;
bar_json::serializer()( b, json.begin(), json.end(), nullptr );
b.flag = true;
b.vfoo.push_back( static_cast<const foo&>(b));
b.pfoo = std::make_shared<foo>(static_cast<const foo&>(b));
std::cout << json << std::endl;
bar_json::serializer()(b, std::ostream_iterator<char>(std::cout) );
std::cout << std::endl;
}Вывод:
[true,0,"Привет Мир",[],"pfoo":null]
[true,0,"Привет Мир",[[true,0,"Привет Мир"]],[true,0,"Привет Мир"]]