Skip to content

ObjectJson

Владимир Мигашко edited this page Sep 5, 2016 · 4 revisions

<< Назад

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,"Привет Мир"]]

<< Назад

Clone this wiki locally