94
Упрощаем переход от JSON к C++ структурам и обратно Николай Гродзицкий

упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Embed Size (px)

Citation preview

Page 1: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Упрощаем переход от JSON к C++ структурам и

обратноНиколай Гродзицкий

Page 2: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

О чем пойдет речь?

2

Page 3: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

О чем пойдет речь?DTO

struct message_source_t{ // Worker thread. std::int32_t m_thread_id;

// Sender. std::string m_subsystem;};

struct message_t{ // Who sent a message. message_source_t m_from;

// When the message was sent (unixtime). std::tm m_when;

// Message text. std::string m_text;}; 3

Page 4: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

О чем пойдет речь?DTO

struct message_source_t{ // Worker thread. std::int32_t m_thread_id;

// Sender. std::string m_subsystem;};

struct message_t{ // Who sent a message. message_source_t m_from;

// When the message was sent (unixtime). std::tm m_when;

// Message text. std::string m_text;};

JSON

“JSON (JavaScript Object Notation) is a lightweight data-interchange format.”

http://www.json.org/

4

Page 5: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

О чем пойдет речь?DTO

struct message_source_t{ // Worker thread. std::int32_t m_thread_id;

// Sender. std::string m_subsystem;};

struct message_t{ // Who sent a message. message_source_t m_from;

// When the message was sent (unixtime). std::tm m_when;

// Message text. std::string m_text;};

JSON

“JSON (JavaScript Object Notation) is a lightweight data-interchange format.”

http://www.json.org/

{ "from" : { "thread_id" : 4242, "sybsystem" : "json_dto" }, "when" : "2016.09.28 19:55:00" , "text" : "Hello world!"}

5

Page 6: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?

6

Page 8: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?

8

Page 9: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?I'd like to create a JSON string containing the instance variables of my class.For example,

class Example { std::string string; std::map<std::string, std:string> map; std::vector<int> vector; };

would become:

{ "string":"the-string-value", "map": { "key1":"val1", "key2":"val2" }, "vector":[1,2,3,4]}

9

Page 10: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?“I want a way to serialize and deserialize Objects to JSON, as automatic as possible.”

“Serialize: For me, the ideal way is that if I call in an instance JSONSerialize() it returns an string with a JSON object that has all the public properties of the object as "name_of_property": "value".”

“Deserialize: Just make an instance of the given object (let's say a dog) and call JSONDeserialize(json_string), and that should fill all the public properties, creating the needed objects in case that the properties are not primitives, or the needed collections.”

10

Page 11: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?

“Is there any simple way to convert a json string in an object and back as shown in this example? (http://www.newtonsoft.com/json/help/html/serializingjson.htm)”

11

Page 12: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Это кому-нибудь нужно?

В целом, хочется для заданной структуры (класса) иметь возможность конвертировать инстанс в JSON и наоборот получить инстанс из JSON.

При этом чтобы дополнительного кода требовалось как можно меньше.

12

Page 13: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?

13

Page 14: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

14

Page 15: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSON

15

Page 16: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

16

Page 17: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

17

Page 18: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)

18

Page 19: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)■ зависит только от RapidJSON (тоже header-only)

19

Page 20: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода

20

Page 21: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода

■ Механика описания правил позаимствована у Boost Serialization

21

Page 22: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода

■ Механика описания правил позаимствована у Boost Serialization■ Для одного DTO требуется написать одну функцию

22

Page 23: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов

23

Page 24: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов

■ Простые типы: String, Number, Bool

24

Page 25: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов

■ Простые типы: String, Number, Bool■ Массивы (Array)

25

Page 26: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов

■ Простые типы: String, Number, Bool■ Массивы (Array)■ Объекты (Object)

26

Page 27: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов○ Поддержка null-полей

27

Page 28: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что такое json_dto?● Нет, это не еще один JSON парсер

○ В качестве парсера используется RapidJSONВыбор был сделан на основе nativejson-benchmark

● Инструмент для отображения DTO в JSON и обратно по заданным правилам

○ Header-only (C++14)○ Требует немного дополнительного кода○ Интуитивно понятная поддержка типов○ Поддержка null-полей○ Опциональные поля и значения по умолчанию

28

Page 29: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Давайте посмотрим, что умеет json_dto

29

Page 30: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!struct message_t{ std::string m_from; std::string m_text;};

30

Page 31: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!struct message_t{ std::string m_from; std::string m_text;};

{ "from" : "<from>", "text" : "<text>" }

31

Page 32: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!struct message_t{ std::string m_from; std::string m_text;};

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

32

Page 33: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!Чтение:const std::string json_data{ R"({ "from" : "json_dto", "text" : "Hello world!" })" };

auto msg = json_dto::from_json< message_t >( json_data );

Запись:auto json_str = json_dto::to_json( msg );

#include <json_dto/pub.hpp >// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

33

Page 34: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!Чтение:const std::string json_data{ R"({ "from" : "json_dto", "text" : "Hello world!" })" };

auto msg = json_dto::from_json< message_t >( json_data );

Запись:auto json_str = json_dto::to_json( msg );

template < typename TYPE, unsigned RAPIDJSON_PARSEFLAGS = rapidjson::kParseDefaultFlags >TYPEfrom_json( const std::string & json );

34

Page 35: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Hello world!Чтение:const std::string json_data{ R"({ "from" : "json_dto", "text" : "Hello world!" })" };

auto msg = json_dto::from_json< message_t >( json_data );

Запись:auto json_str = json_dto::to_json( msg );

template < typename DTO >std::stringto_json( const DTO & dto );

35

Page 36: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какую роль играет json_io()

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

36

Page 37: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какую роль играет json_io()Это входная точка для json_dto.

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

37

Page 38: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какую роль играет json_io()Это входная точка для json_dto, она служит для описания:

● как читать DTO из JSON;● как писать DTO в JSON.

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

38

Page 39: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какую роль играет json_io()Это входная точка для json_dto, она служит для описания:

● как читать DTO из JSON;● как писать DTO в JSON.

Шаблонной она является, для того чтобы иметь всего одну логику для записи и чтения.

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

39

Page 40: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какую роль играет json_io()Это входная точка для json_dto, она служит для описания:

● как читать DTO из JSON;● как писать DTO в JSON.

Шаблонной она является, для того чтобы иметь всего одну логику для записи и чтения.

json_dto подставляет в нее объекты двух типов:

● json_dto::json_input_t● json_dto::json_output_t

#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

40

Page 41: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Внутри json_io()#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

41

Page 42: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Внутри json_io()#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

42

io & binder

Page 43: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Внутри json_io()#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

43

io & binder

json_input_t

json_ouput_t

Page 44: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Внутри json_io()#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

44

io & binder

json_input_t

json_ouput_tАналог

operator<< operator>>

Page 45: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Внутри json_io()#include <json_dto/pub.hpp>// ...

struct message_t{ std::string m_from; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ); }};

45

io & binder

json_input_t

json_ouput_tАналог

operator<< operator>>

Привязка

Page 46: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязки

46

Page 47: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязки● mandatory (обязательные)

template < typename FIELD_TYPE, typename VALIDATOR = empty_validator_t >automandatory( string_ref_t field_name, FIELD_TYPE & field, VALIDATOR validator = VALIDATOR{} );

struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain" }; bool m_is_private{ false };

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "text_format", m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", m_is_private ); }};

47

Page 48: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязки● optional (необязательные со

значением по умолчанию)

template < typename FIELD_TYPE, typename FIELD_DEFAULT_VALUE_TYPE, typename VALIDATOR = empty_validator_t >autooptional( string_ref_t field_name, FIELD_TYPE & field, FIELD_DEFAULT_VALUE_TYPE default_value, VALIDATOR validator = VALIDATOR{} );

struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain" }; bool m_is_private{ false };

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "text_format", m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", m_is_private ); }};

48

Page 49: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязкиПусть мы имеем:auto msg = json_dto::from_json<message_t>(json );

тогда:1. {"from":"...","text":"..." }

msg.m_text_format == "text/plain"

2. {"from":"...","text":"...", "text_format": "text/html" }

msg.m_text_format == "text/html"

struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain" }; bool m_is_private{ false };

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "text_format", m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", m_is_private ); }};

49

Page 50: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязки● optional_no _default

(необязательные, без значения по умолчанию)

template < typename FIELD_TYPE, typename VALIDATOR = empty_validator_t >autooptional_no_default( string_ref_t field_name, FIELD_TYPE & field, VALIDATOR validator = VALIDATOR{} );

struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain" }; bool m_is_private{ false };

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "text_format", m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", m_is_private ); }};

50

Page 51: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Почему отдельные имена optional_no_default() и optional()template < typename FIELD_TYPE, typename FIELD_DEFAULT_VALUE_TYPE, typename VALIDATOR = empty_validator_t >autooptional( string_ref_t field_name, FIELD_TYPE & field, FIELD_DEFAULT_VALUE_TYPE default_value, VALIDATOR validator = VALIDATOR{} );

template < typename FIELD_TYPE, typename VALIDATOR = empty_validator_t >autooptional_no_default( string_ref_t field_name, FIELD_TYPE & field, VALIDATOR validator = VALIDATOR{} );

51

Page 52: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Какие бывают привязки● mandatory (обязательные)

● optional (необязательные со значением по умолчанию)

● optional_no _default (необязательные, без значения по умолчанию)

52

Page 53: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддерживаемые типы

53

Page 54: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Простые типыC++

?

http://json.org/

JSON

54

Page 55: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Простые типыC++

● Bool: bool;

http://json.org/

JSON

55

Page 56: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Простые типыC++

● Bool: bool;● Number:

std::int16_t, std::uint16_t, std::int32_t, std::uint32_t, std::int64_t, std::uint64_t, double;

http://json.org/

JSON

56

Page 57: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Простые типыC++

● Bool: bool;● Numeric:

std::int16_t, std::uint16_t, std::int32_t, std::uint32_t, std::int64_t, std::uint64_t, double;

● String: std::stringhttp://json.org/

JSON

57

Page 58: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

“Сложные” типыC++

В json_dto также поддерживаются:

● Массивы● Вложенные DTO

http://json.org/

JSON

58

Page 59: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

“Сложные” типыC++

В json_dto также поддерживаются:

● Массивы● Вложенные DTO

А также в состав json_dto входит обертка для обработки null-значений

http://json.org/

JSON

59

Page 60: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка массивовjson_dto автоматически понимает, что значение поля должно быть массивом, если в качестве второго аргумента для привязки указывается ссылка на std::vector< ELEMENT_TYPE > &

Например:

struct str_array_t{ std::vector< std::string > m_strings;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "strings", m_strings ); }};

60

Page 61: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка массивовНо есть два существенных ограничения:

61

Page 62: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка массивовНо есть два существенных ограничения:

● При чтении массива все элементы должны быть одного типа

62

Page 63: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка массивовНо есть два существенных ограничения:

● При чтении массива все элементы должны быть одного типа

● Значение по умолчанию для массивов в общем случае не работает

63

Page 64: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка вложенных DTOВложенные объекты поддерживаются аналогично простым типам.

Достаточно чтобы тип был уже интегрирован с json_dto.

64

Page 65: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка вложенных DTOstruct needle_t{ std::string m_death{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "death", m_death ); }};

65

Page 66: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка вложенных DTOstruct egg_t{ needle_t m_needle{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "needle", m_needle ); }};

struct needle_t{ std::string m_death{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "death", m_death ); }};

66

Page 67: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка вложенных DTOstruct duck_t{ egg_t m_egg{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "egg", m_egg ); }};

struct needle_t{ std::string m_death{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "death", m_death ); }};

struct egg_t{ needle_t m_needle{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "needle",m_needle ); }}; 67

Page 68: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка вложенных DTOstruct duck_t{ egg_t m_egg{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "egg", m_egg ); }};

struct needle_t{ std::string m_death{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "death", m_death ); }};

struct egg_t{ needle_t m_needle{};

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "needle",m_needle ); }}; 68

Page 69: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийДля поддержки null значений в json_dto предусмотрен класс json_dto::nullable_t<T>.

69

Page 70: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийДля поддержки null значений в json_dto предусмотрен класс json_dto::nullable_t<T>.

Интерфейс json_dto::nullable_t<T> подражает std::optional (C++17).

70

Page 71: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийДля поддержки null значений в json_dto предусмотрен класс json_dto::nullable_t<T>.

Интерфейс json_dto::nullable_t<T> подражает std::optional (C++17).

Требует явного объявления члена-данных с типом json_dto::nullable_t<T>.

71

Page 72: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

72

Page 73: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

{ "from" : "json_dto", "text" : "Hello CoreHard!", "tags" : [ "C++", "JSON", "CoreHard.by" ]}

73

Page 74: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

{ "from" : "json_dto", "text" : "Hello world!", "tags" : [ "C++", "JSON", "CoreHard.by" ]}

{ "from" : "json_dto", "text" : "Hello world!", "tags" : null}

74

Page 75: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

{ "from" : "json_dto", "text" : "Hello world!", "tags" : [ "C++", "JSON", "CoreHard.by" ]}

{ "from" : "json_dto", "text" : "Hello world!", "tags" : null}

{ "from" : "json_dto", "text" : "Hello world!"} 75

Page 76: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

auto msg = json_dto::from_json< message_t >( json_data );

// ...

if( msg.m_tags ){ for( const auto & tag : *msg.m_tags ) { do_smth( tag ); }}else do_smth_else();

76

Page 77: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

auto msg = json_dto::from_json< message_t >( json_data );

// ...

if( msg.m_tags ){ for( const auto & tag : *msg.m_tags ) { do_smth( tag ); }}else do_smth_else();

nullable_t::operator bool () const;77

Page 78: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

auto msg = json_dto::from_json< message_t >( json_data );

// ...

if( msg.m_tags ){ for( const auto & tag : *msg.m_tags ) { do_smth( tag ); }}else do_smth_else();

const FIELD_TYPE &nullable_t::operator * () const; 78

Page 79: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

message_t msg = create_msg( /* ... */ );

// ...

msg.m_tags.reset();

// ...

msg.m_tags = std::vector< std::string >{ "1", "23" };

msg.m_tags->push_back( "42" );

voidnullable_t::reset(); 79

Page 80: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

message_t msg = create_msg( /* ... */ );

// ...

msg.m_tags.reset();

// ...

msg.m_tags = std::vector< std::string >{ "1", "23" };

msg.m_tags->push_back( "42" );

nullable_t &nullable_t::operator= ( FIELD_TYPE && value ); 80

Page 81: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Обработка null-значенийstruct message_t{ std::string m_from; std::string m_text; json_dto::nullable_t< std::vector< std::string > > m_tags;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "tags", m_tags, nullptr ); }};

message_t msg = create_msg( /* ... */ );

// ...

msg.m_tags.reset();

// ...

msg.m_tags = std::vector< std::string >{ "1", "23" };

msg.m_tags->push_back( "42" );

FIELD_TYPE *nullable_t::operator-> (); 81

Page 82: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Что еще?Есть возможность задать неинтрузивный json_io().

Еще есть валидаторы, которые можно задавать самому, но есть и немного стандартных.

Можно определять способ чтения и записи кастомных типов.

82

Page 83: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Неинтрузивный json_io()struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain"}; bool m_is_private{ false };};

83

Page 84: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Неинтрузивный json_io()struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain"}; bool m_is_private{ false };};

84

namespace json_dto{

template < typename JSON_IO > void json_io( JSON_IO & io, message_t & msg ) { io & json_dto::mandatory( "from", msg.m_from ) & json_dto::mandatory( "text", msg.m_text ) & json_dto::optional( "text_format", msg.m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", msg.m_is_private ); }

} /* namespace json_dto */

Page 85: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Неинтрузивный json_io()struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain"}; bool m_is_private{ false };};

85

namespace json_dto{

template < typename JSON_IO > void json_io( JSON_IO & io, message_t & msg ) { io & json_dto::mandatory( "from", msg.m_from ) & json_dto::mandatory( "text", msg.m_text ) & json_dto::optional( "text_format", msg.m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", msg.m_is_private ); }

} /* namespace json_dto */

Page 86: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Неинтрузивный json_io()struct message_t{ std::string m_from{}; std::string m_text{}; std::string m_text_format{ "text/plain"}; bool m_is_private{ false };};

86

namespace json_dto{

template < typename JSON_IO > void json_io( JSON_IO & io, message_t & msg ) { io & json_dto::mandatory( "from", msg.m_from ) & json_dto::mandatory( "text", msg.m_text ) & json_dto::optional( "text_format", msg.m_text_format, "text/plain" ) & json_dto::optional_no_default( "is_private", msg.m_is_private ); }

} /* namespace json_dto */

Page 87: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка кастомных типов

87

Page 88: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка кастомных типовstruct message_t{ std::string m_from; std::tm m_when; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "when", m_when ) & json_dto::mandatory( "text", m_text ); }};

88

Page 89: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка кастомных типовstruct message_t{ std::string m_from; std::tm m_when; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "when", m_when ) & json_dto::mandatory( "text", m_text ); }};

89

Page 90: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Поддержка кастомных типовstruct message_t{ std::string m_from; std::tm m_when; std::string m_text;

template < typename JSON_IO > void json_io( JSON_IO & io ) { io & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "when", m_when ) & json_dto::mandatory( "text", m_text ); }};

namespace json_dto{

template <>voidread_json_value( const rapidjson::Value & object, std::tm & v ){ // ...}

template <>voidwrite_json_value( const std::tm & v, rapidjson::Value & object, rapidjson::MemoryPoolAllocator<> & allocator ){ // ...}

} /* namespace json_dto */

90

Page 91: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

ВалидаторыФункциональный объект (function object), который получает один параметр.

Если значение корректно, то валидатор просто штатно завершает свою работу.

Если значение некорректное, то валидатор должен выбросить исключение.

91

Page 92: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Валидаторыio & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "log_level", m_log_level, nullptr );

92

Page 93: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Валидаторыio & json_dto::mandatory( "from", m_from ) & json_dto::mandatory( "text", m_text ) & json_dto::optional( "log_level", m_log_level, nullptr );

io & json_dto::mandatory( "from", m_from, []( const auto & from ){ if( from.empty() ) throw std::runtime_error{ "from cannot be empty" }; } ) & json_dto::mandatory( "text", m_text, check_all_7bit ) & json_dto::optional( "log_level", m_log_level,nullptr, json_dto::one_of_constraint( { std::string{ "trace" }, std::string{ "info" },std::string{ "error" } } ) );

93

Page 94: упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)

Спасибо!Николай Гродзицкий[email protected]

https://bitbucket.org/sobjectizerteam/json_dto-0.1

https://github.com/miloyip/rapidjson

http://www.boost.org/doc/libs/1_62_0/libs/serialization/doc/index.html

http://en.cppreference.com/w/cpp/utility/optional

Альтернативы: https://github.com/Loki-Astari/ThorsSerializer.git

94