在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:jorgen/json_struct开源软件地址:https://github.com/jorgen/json_struct开源编程语言:C++ 98.9%开源软件介绍:Structurize your JSONjson_struct is a single header only library that parses JSON to C++ structs/classes and serializing structs/classes to JSON. It is intended to be used by copying the json_struct.h file from the include folder into the include path for the project. It is only the json_struct.h file that is needed to serialize and deserialize json from structures. It is dependent on some C++11 features and is tested on newer versions of gcc and clang. It is also tested on VS 2015 and newer. Structsjson_struct can parse JSON and automatically populate structures with content by adding some metadata to the C++ structs. {
"One" : 1,
"Two" : "two",
"Three" : 3.333
} can be parsed into a structure defined like this: struct JsonObject
{
int One;
std::string Two;
double Three;
JS_OBJ(One, Two, Three);
}; or struct JsonObject
{
int One;
std::string Two;
double Three;
};
JS_OBJ_EXT(JsonObject, One, Two, Three); Populating the struct would look like this: JS::ParseContext context(json_data);
JsonObject obj;
context.parseTo(obj); Serializing the struct to json could be done like this: std::string pretty_json = JS::serializeStruct(obj);
// or
std::string compact_json = JS::serializeStruct(obj, JS::SerializerOptions(JS::SerializerOptions::Compact)); MapsSometimes the structure of the JSON is dependent on some value in the JSON. Say there is some input JSON that describes a transportation vehicle. It can looks something like this {
"type" : "car",
"wheels" : 4,
"electric" : true,
...
} or it could look like this: {
"type" : "sailboat",
"sail_area_m2" : 106.5,
"swimming_platform": true,
...
} This doesn't fit well with the static nature of json_struct. However, it is possible to parse the JSON into a map structure, query some child members for data and then dispatch the conversion into an appropriate type. void handle_data(const char *data, size_t size)
{
JS::Map map;
JS::ParseContext parseContext(data, size, map);
if (parseContext.error != JS::Error::NoError)
{
fprintf(stderr, "Failed to parse Json:\n%s\n", parseContext.makeErrorString().c_str());
return;
}
VehicleType vehicleType = map.castTo<VehicleType>("type", parseContext);
if (parseContext.error != JS::Error::NoError)
{
fprintf(stderr, "Failed to extract type:\n%s\n", parseContext.makeErrorString().c_str());
return;
}
switch (vehicleType)
{
case VehicleType::car:
{
Car car = map.castTo<Car>(parseContext);
if (parseContext.error != JS::Error::NoError)
{
//error handling
}
handle_car(car);
break;
}
case VehicleType::sailboat:
Sailboat sailboat;
map.castToType(parseContext, sailboat);
if (parseContext.error != JS::Error::NoError)
{
//error handling
}
handle_sailboat(sailboat);
break;
}
} Here we parse the JSON into a VehicleType vehicleType = map.castTo<VehicleType>("type", parseContext); Then we can inspect the value of the type child and cast the entire object into
the desired type. The Car car = map.castTo<Car>(parseContext);
// or
Sailboat sailboat;
map.castToType(parseContext, sailboat); Demystifying the MacrosThe JS_OBJ macro adds a static meta object to the struct/class. It does not affect the semantics or size of the struct/class. It automatically applies another macro to the member arguments, getting the name and member pointer. There are other macros that are more verbose, but that gives more flexibility. The JS_OBJECT macro requires that all the members are passed in a JS_MEMBER macro. An example of these macros being applied would look like this: struct JsonObject
{
int One;
std::string Two;
double Three;
JS_OBJECT(JS_MEMBER(One)
, JS_MEMBER(Two)
, JS_MEMBER(Three));
}; This doesn't add any value, but say you want to have a different JSON key for a member than the name, or maybe you want to add some alias keys, then this could be done like this: struct JsonObject
{
int One;
std::string Two;
double Three;
JS_OBJECT(JS_MEMBER(One)
, JS_MEMBER_WITH_NAME(Two, "TheTwo")
, JS_MEMBER_ALIASES(Three, "TheThree", "the_three"));
}; The difference between the _WITH_NAME and _ALIASES macros is that the _WITH_NAME macro ignores the member name and uses the supplied name, while the aliases adds a list of names to be checked after the name of the member is checked. Its not possible to use the JS_MEMBER macros with the JS_OBJ macro, since then it tries to apply the JS_MEMBER macro twice on member. TypeHandlerFor objects the meta information is generated with JS_OBJ and JS_OBJECT macros, but there might be types that doesn't fit the meta information interface, ie they are not JSON Object types. Then its possible to define how these specific classes are serialized and deserialized with the TypeHandler interface. When the JS::ParseContext tries to parse a type it will look for a template specialisation of the type: namespace JS {
template<typename T>
struct TypeHandler;
} There are a number of predefined template specialisations for types such as:
Its not often necessary, but when you need to define your own serialization and deserialization it's done like this: namespace JS {
template<>
struct TypeHandler<uint32_t>
{
public:
static inline Error to(uint32_t &to_type, ParseContext &context)
{
char *pointer;
unsigned long value = strtoul(context.token.value.data, &pointer, 10);
to_type = static_cast<unsigned int>(value);
if (context.token.value.data == pointer)
return Error::FailedToParseInt;
return Error::NoError;
}
static void from(const uint32_t &from_type, Token &token, Serializer &serializer)
{
std::string buf = std::to_string(from_type);
token.value_type = Type::Number;
token.value.data = buf.data();
token.value.size = buf.size();
serializer.write(token);
}
};
} This gives you complete control of serialization deserialization of a type and it can unfold to a JSON object or array if needed. For more information checkout the examples at: https://github.com/jorgen/json_struct/tree/master/examples and have a look at the more complete unit tests at: https://github.com/jorgen/json_struct/tree/master/tests |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论