La version prĂ©cĂ©dente de la rĂ©solution du problĂšme du mappage entre la structure C ++ et json s'est avĂ©rĂ©e comme la premiĂšre crĂȘpe - un morceau. Heureusement, le dĂ©veloppement est un processus itĂ©ratif et il y aura toujours une deuxiĂšme version derriĂšre la premiĂšre version. Les commentaires (merci Ă tous) et l'analyse des trous dans la premiĂšre crĂȘpe ont apportĂ© quelques amĂ©liorations.
Ce qui Ă©tait mauvais
- il est impossible d'utiliser des structures C ++ ordinaires (y compris celles dĂ©jĂ existantes). Toutes les structures doivent ĂȘtre dĂ©finies Ă partir de zĂ©ro d'une maniĂšre spĂ©ciale
- L'objet Json ne peut ĂȘtre mappĂ© qu'Ă une structure spĂ©cialement dĂ©finie
- Le tableau Json ne peut ĂȘtre mappĂ© qu'Ă une classe spĂ©ciale
- il est impossible d'utiliser des conteneurs stl
- les macros sont simplement nécessaires (c'est possible sans elles, mais l'enregistrement des méthodes de paramétrage des champs est rigidement combiné avec l'initialisation de ces champs, donc, sans macros, la définition de la structure est illisible)
- l'affichage n'est en aucun cas configurable, c'est-Ă -dire ne peut pas ĂȘtre dĂ©fini, par exemple, des valeurs par dĂ©faut ou des limites de valeur
Comment c'est devenu maintenant
L'enregistrement des champs qui participeront à l'affichage n'est plus lié à la structure. Pour vous inscrire, utilisez la fonction
reg(V T::* ptr, std::string const & name, Options<U>&& ... options);
ptr
- pointeur vers le champname
- nom de domaineoptions
- option d'affichage
Les Ă©lĂ©ments suivants peuvent ĂȘtre utilisĂ©s comme types de champ:
- booléen
- char, unsigned char, short, unsigned short, int unsigned int, long, long long
- flotteur, double
- std :: string
- std :: list
- std :: vecteur
- std::map ( std::string)
- std::unordered_map ( std::string)
- std::multimap ( std::string)
- std::unordered_multimap ( std::string)
- ++
struct Friend {
std::string name;
std::list<int> counters;
};
struct MiB {
std::list<Friend> friends;
std::vector<std::list<std::string>> groups;
std::map<std::string, std::vector<std::string>> books;
};
struct_mapping::reg(&Friend::name, "name");
struct_mapping::reg(&Friend::counters, "counters");
struct_mapping::reg(&MiB::friends, "friends");
struct_mapping::reg(&MiB::groups, "groups");
struct_mapping::reg(&MiB::books, "books");
, ,
map_json_to_struct(T & result_struct, std::basic_istream<char> & json_data);
result_struct
âjson_data
â json
. .
#include <iostream>
#include <sstream>
#include "struct_mapping/struct_mapping.h"
struct Planet {
bool giant;
long long surface_area;
double mass;
std::string satellite;
};
int main() {
struct_mapping::reg(&Planet::giant, "giant");
struct_mapping::reg(&Planet::surface_area, "surface_area");
struct_mapping::reg(&Planet::mass, "mass");
struct_mapping::reg(&Planet::satellite, "satellite");
Planet earth;
std::istringstream json_data(R"json(
{
"giant": false,
"surface_area": 510072000000000,
"mass": 5.97237e24,
"satellite": "Moon"
}
)json");
struct_mapping::map_json_to_struct(earth, json_data);
std::cout << "earth" << std::endl;
std::cout << " giant : " << std::boolalpha << earth.giant << std::endl;
std::cout << " surface_area : " << earth.surface_area << std::endl;
std::cout << " mass : " << earth.mass << std::endl;
std::cout << " satellite : " << earth.satellite << std::endl;
}
earth
giant : false
surface_area : 510072000000000
mass : 5.97237e+24
satellite : Moon
, json . , :
MemberString::set(From function_from_string_, To function_to_string_);
function_from_string_
âfunction_to_string_
â
enum class Color {
red,
blue,
green,
};
struct_mapping::MemberString<Color>::set(
[] (const std::string & value) {
if (value == "red") return Color::red;
if (value == "green") return Color::green;
if (value == "blue") return Color::blue;
throw struct_mapping::StructMappingException("bad convert '"+value+"' to Color");
},
[] (Color value) {
switch (value) {
case Color::red: return "red";
case Color::green: return "green";
default: return "blue";
}
});
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include "struct_mapping/struct_mapping.h"
namespace sm = struct_mapping;
enum class Color {
red,
blue,
green,
};
Color color_from_string(const std::string & value) {
if (value == "red") return Color::red;
if (value == "blue") return Color::blue;
return Color::green;
}
std::string color_to_string(Color color) {
switch (color) {
case Color::red: return "red";
case Color::green: return "green";
default: return "blue";
}
}
struct Palette {
Color main_color;
Color background_color;
std::list<Color> special_colors;
std::map<std::string, Color> colors;
friend std::ostream & operator<<(std::ostream & os, const Palette & o) {
os << "main_color : " << color_to_string(o.main_color) << std::endl;
os << "background_color : " << color_to_string(o.background_color) << std::endl;
os << "special_colors : ";
for (auto color : o.special_colors)
os << color_to_string(color) << ", ";
os << std::endl << "colors : ";
for (auto [name, color] : o.colors)
os << "[" << name << ", " << color_to_string(color) << "], ";
os << std::endl;
return os;
}
};
int main() {
sm::MemberString<Color>::set(color_from_string, color_to_string);
sm::reg(&Palette::main_color, "main_color", sm::Required{});
sm::reg(&Palette::background_color, "background_color", sm::Default{Color::blue});
sm::reg(&Palette::special_colors, "special_colors");
sm::reg(&Palette::colors, "colors");
Palette palette;
std::istringstream json_data(R"json(
{
"main_color": "green",
"special_colors": ["green", "green", "red"],
"colors": {
"dark": "green",
"light": "red",
"neutral": "blue"
}
}
)json");
sm::map_json_to_struct(palette, json_data);
std::cout << palette << std::endl;
}
main_color : green
background_color : blue
special_colors : green, green, red,
colors : [dark, green], [light, red], [neutral, blue],
,
- Bounds
- Default
- NotEmpty
- Required
Bounds
, ( ) . . â . .
Bounds{ , }
:
reg(&Stage::engine_count, "engine_count", Bounds{1, 31});
Default
. bool, , , , , ++ . â .
Default{ }
:
reg(&Stage::engine_count, "engine_count", Default{3});
NotEmpty
, . . . , .
:
reg(&Spacecraft::name, "name", NotEmpty{}));
Required
, . bool, , , , , ++ . . , .
:
reg(&Spacecraft::name, "name", Required{}));
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include "struct_mapping/struct_mapping.h"
namespace sm = struct_mapping;
struct Stage {
unsigned short engine_count;
std::string fuel;
long length;
friend std::ostream & operator<<(std::ostream & os, const Stage & o) {
os << " engine_count : " << o.engine_count << std::endl;
os << " fuel : " << o.fuel << std::endl;
os << " length : " << o.length << std::endl;
return os;
}
};
struct Spacecraft {
bool in_development;
std::string name;
int mass;
std::map<std::string, Stage> stages;
std::list<std::string> crew;
friend std::ostream & operator<<(std::ostream & os, const Spacecraft & o) {
os << "in_development : " << std::boolalpha << o.in_development << std::endl;
os << "name : " << o.name << std::endl;
os << "mass : " << o.mass << std::endl;
os << "stages: " << std::endl;
for (auto& s : o.stages) os << " " << s.first << std::endl << s.second;
os << "crew: " << std::endl;
for (auto& p : o.crew) os << " " << p << std::endl;
return os;
}
};
int main() {
sm::reg(&Stage::engine_count, "engine_count", sm::Default{6}, sm::Bounds{1, 31});
sm::reg(&Stage::fuel, "fuel", sm::Default{"subcooled"});
sm::reg(&Stage::length, "length", sm::Default{50});
sm::reg(&Spacecraft::in_development, "in_development", sm::Required{});
sm::reg(&Spacecraft::name, "name", sm::NotEmpty{});
sm::reg(&Spacecraft::mass, "mass",
sm::Default{5000000}, sm::Bounds{100000, 10000000});
sm::reg(&Spacecraft::stages, "stages", sm::NotEmpty{});
sm::reg(&Spacecraft::crew, "crew",
sm::Default{std::list<std::string>{"Arthur", "Ford", "Marvin"}});
Spacecraft starship;
std::istringstream json_data(R"json(
{
"in_development": false,
"name": "Vostok",
"stages": {
"first": {
"engine_count": 31,
"fuel": "compressed gas",
"length": 70
},
"second": {}
}
}
)json");
sm::map_json_to_struct(starship, json_data);
std::cout << starship << std::endl;
}
in_development : false
name : Vostok
mass : 5000000
stages:
first
engine_count : 31
fuel : compressed gas
length : 70
second
engine_count : 6
fuel : subcooled
length : 50
crew:
Arthur
Ford
Marvin
c++ json
json , ,
reg(V T::* ptr, std::string const & name, Options<U>&& ... options);
map_struct_to_json(T & source_struct, std::basic_ostream<char> & json_data, std::string indent);
source_struct
âjson_data
â jsonindent
â ( , )
#include <iostream>
#include <sstream>
#include "struct_mapping/struct_mapping.h"
struct OceanPart {
std::string name;
double average_depth;
std::vector<int> temperature;
};
struct OceanColor {
std::string name;
};
struct Ocean {
double water_volume;
long long surface_area;
bool liquid;
std::string name;
OceanColor color;
std::vector<OceanPart> parts;
};
struct Planet {
bool giant;
long long surface_area;
double mass;
double volume;
long long orbital_period;
std::string name;
bool terrestrial;
std::string shape;
Ocean ocean;
};
int main() {
struct_mapping::reg(&OceanPart::name, "name");
struct_mapping::reg(&OceanPart::average_depth, "average_depth");
struct_mapping::reg(&OceanPart::temperature, "temperature");
struct_mapping::reg(&OceanColor::name, "name");
struct_mapping::reg(&Ocean::water_volume, "water_volume");
struct_mapping::reg(&Ocean::surface_area, "surface_area");
struct_mapping::reg(&Ocean::liquid, "liquid");
struct_mapping::reg(&Ocean::name, "name");
struct_mapping::reg(&Ocean::color, "color");
struct_mapping::reg(&Ocean::parts, "parts");
struct_mapping::reg(&Planet::giant, "giant");
struct_mapping::reg(&Planet::surface_area, "surface_area");
struct_mapping::reg(&Planet::mass, "mass");
struct_mapping::reg(&Planet::volume, "volume");
struct_mapping::reg(&Planet::orbital_period, "orbital_period");
struct_mapping::reg(&Planet::name, "name");
struct_mapping::reg(&Planet::terrestrial, "terrestrial");
struct_mapping::reg(&Planet::shape, "shape");
struct_mapping::reg(&Planet::ocean, "ocean");
Planet earth;
earth.giant = false;
earth.terrestrial = true;
earth.surface_area = 510072000;
earth.orbital_period = 365 * 24 * 3600;
earth.mass = 5.97237e24;
earth.name = "Terra";
earth.volume = 1.08321e12;
earth.shape = "nearly spherical";
earth.ocean.water_volume = 1332000000;
earth.ocean.surface_area = 361132000;
earth.ocean.liquid = true;
earth.ocean.name = "World Ocean";
earth.ocean.color.name = "blue";
OceanPart pacific;
pacific.name = "Pacific Ocean";
pacific.average_depth = 4.280111;
pacific.temperature = std::vector<int>{-3, 5, 12};
OceanPart atlantic;
atlantic.name = "Atlantic Ocean";
atlantic.average_depth = 3.646;
atlantic.temperature = std::vector<int>{-3, 0};
earth.ocean.parts.push_back(pacific);
earth.ocean.parts.push_back(atlantic);
std::ostringstream json_data;
struct_mapping::map_struct_to_json(earth, json_data, " ");
std::cout << json_data.str() << std::endl;
}
{
"giant": false,
"surface_area": 510072000,
"mass": 5.97237e+24,
"volume": 1.08321e+12,
"orbital_period": 31536000,
"name": "Terra",
"terrestrial": true,
"shape": "nearly spherical",
"ocean": {
"water_volume": 1.332e+09,
"surface_area": 361132000,
"liquid": true,
"name": "World Ocean",
"color": {
"name": "blue"
},
"parts": [
{
"name": "Pacific Ocean",
"average_depth": 4.28011,
"temperature": [
-3,
5,
12
]
},
{
"name": "Atlantic Ocean",
"average_depth": 3.646,
"temperature": [
-3,
0
]
}
]
}
}
- ++ ( )
- Les objets Json peuvent ĂȘtre mappĂ©s Ă la fois sur une structure spĂ©cialement dĂ©finie (cette possibilitĂ© demeure) et sur des structures ordinaires
- Les tableaux Json peuvent ĂȘtre mappĂ©s vers std :: vector et std :: list. Les exigences gĂ©nĂ©rales pour les conteneurs sur lesquels les rĂ©seaux peuvent ĂȘtre mappĂ©s ne sont pas encore complĂštement formĂ©es.
- Les objets json peuvent ĂȘtre mappĂ©s Ă des conteneurs associatifs, avec la restriction que la clĂ© doit ĂȘtre une chaĂźne. Les exigences gĂ©nĂ©rales pour les conteneurs, ainsi que pour les tableaux, ne sont pas encore complĂštement formĂ©es.
- les macros sont inutiles et certainement pas nécessaires. La possibilité de les utiliser restait (en option) lors de l'inscription, combinée à l'initialisation des champs. Mais trÚs probablement, il sera coupé.
- l'affichage peut ĂȘtre personnalisĂ© Ă l'aide d'options