On 8/31/21 2:26 AM, Han Zhou wrote: > > > On Tue, Aug 24, 2021 at 12:00 PM Ilya Maximets <[email protected] > <mailto:[email protected]>> wrote: >> >> Introducing a new json type JSON_SERIALIZED_OBJECT. It's not an >> actual type that can be seen in a json message on a wire, but >> internal type that is intended to hold a serialized version of >> some other json object. For this reason it's defined after the >> JSON_N_TYPES to not confuse parsers and other parts of the code >> that relies on compliance with RFC 4627. >> >> With this JSON type internal users may construct large JSON objects, >> parts of which are already serialized. This way, while serializing >> the larger object, data from JSON_SERIALIZED_OBJECT can be added >> directly to the result, without additional processing. >> >> This will be used by next commits to add pre-serialized JSON data >> to the raft_header structure, that can be converted to a JSON >> before writing the file transaction on disk or sending to other >> servers. Same technique can also be used to pre-serialize json_cache >> for ovsdb monitors, this should allow to not perform serialization >> for every client and will save some more memory. >> >> Since serialized JSON is just a string, reusing the 'json->string' >> pointer for it. >> >> Signed-off-by: Ilya Maximets <[email protected] <mailto:[email protected]>> >> --- >> include/openvswitch/json.h | 9 +++++++-- >> lib/json.c | 34 ++++++++++++++++++++++++++++++++++ >> 2 files changed, 41 insertions(+), 2 deletions(-) >> >> diff --git a/include/openvswitch/json.h b/include/openvswitch/json.h >> index 73b562e03..b8cf49ab6 100644 >> --- a/include/openvswitch/json.h >> +++ b/include/openvswitch/json.h >> @@ -50,7 +50,9 @@ enum json_type { >> JSON_INTEGER, /* 123. */ >> JSON_REAL, /* 123.456. */ >> JSON_STRING, /* "..." */ >> - JSON_N_TYPES >> + JSON_N_TYPES, >> + JSON_SERIALIZED_OBJECT, /* Internal type to hold serialized version >> of >> + * data of other types. */ >> }; >> >> const char *json_type_to_string(enum json_type); >> @@ -70,7 +72,7 @@ struct json { >> struct json_array array; >> long long int integer; >> double real; >> - char *string; >> + char *string; /* JSON_STRING or JSON_SERIALIZED_OBJECT. */ >> }; >> }; >> >> @@ -78,6 +80,7 @@ struct json *json_null_create(void); >> struct json *json_boolean_create(bool); >> struct json *json_string_create(const char *); >> struct json *json_string_create_nocopy(char *); >> +struct json *json_serialized_object_create(const struct json *); >> struct json *json_integer_create(long long int); >> struct json *json_real_create(double); >> >> @@ -99,6 +102,7 @@ void json_object_put_format(struct json *, >> OVS_PRINTF_FORMAT(3, 4); >> >> const char *json_string(const struct json *); >> +const char *json_serialized_object(const struct json *); >> struct json_array *json_array(const struct json *); >> struct shash *json_object(const struct json *); >> bool json_boolean(const struct json *); >> @@ -125,6 +129,7 @@ struct json *json_parser_finish(struct json_parser *); >> void json_parser_abort(struct json_parser *); >> >> struct json *json_from_string(const char *string); >> +struct json *json_from_serialized_object(const struct json *); >> struct json *json_from_file(const char *file_name); >> struct json *json_from_stream(FILE *stream); >> >> diff --git a/lib/json.c b/lib/json.c >> index 32d25003b..6bb620724 100644 >> --- a/lib/json.c >> +++ b/lib/json.c >> @@ -146,6 +146,7 @@ json_type_to_string(enum json_type type) >> case JSON_STRING: >> return "string"; >> >> + case JSON_SERIALIZED_OBJECT: >> case JSON_N_TYPES: >> default: >> return "<invalid>"; >> @@ -180,6 +181,14 @@ json_string_create(const char *s) >> return json_string_create_nocopy(xstrdup(s)); >> } >> >> +struct json * >> +json_serialized_object_create(const struct json *src) >> +{ >> + struct json *json = json_create(JSON_SERIALIZED_OBJECT); >> + json->string = json_to_string(src, JSSF_SORT); >> + return json; >> +} >> + >> struct json * >> json_array_create_empty(void) >> { >> @@ -309,6 +318,13 @@ json_string(const struct json *json) >> return json->string; >> } >> >> +const char * >> +json_serialized_object(const struct json *json) >> +{ >> + ovs_assert(json->type == JSON_SERIALIZED_OBJECT); >> + return json->string; >> +} >> + >> struct json_array * >> json_array(const struct json *json) >> { >> @@ -362,6 +378,7 @@ json_destroy(struct json *json) >> break; >> >> case JSON_STRING: >> + case JSON_SERIALIZED_OBJECT: >> free(json->string); >> break; >> >> @@ -422,6 +439,9 @@ json_deep_clone(const struct json *json) >> case JSON_STRING: >> return json_string_create(json->string); >> >> + case JSON_SERIALIZED_OBJECT: >> + return json_serialized_object_create(json); >> + >> case JSON_NULL: >> case JSON_FALSE: >> case JSON_TRUE: >> @@ -521,6 +541,7 @@ json_hash(const struct json *json, size_t basis) >> return json_hash_array(&json->array, basis); >> >> case JSON_STRING: >> + case JSON_SERIALIZED_OBJECT: >> return hash_string(json->string, basis); >> >> case JSON_NULL: >> @@ -596,6 +617,7 @@ json_equal(const struct json *a, const struct json *b) >> return json_equal_array(&a->array, &b->array); >> >> case JSON_STRING: >> + case JSON_SERIALIZED_OBJECT: >> return !strcmp(a->string, b->string); >> >> case JSON_NULL: >> @@ -1072,6 +1094,14 @@ json_from_string(const char *string) >> return json_parser_finish(p); >> } >> >> +/* Parses data of JSON_SERIALIZED_OBJECT to the real JSON. */ >> +struct json * >> +json_from_serialized_object(const struct json *json) >> +{ >> + ovs_assert(json->type == JSON_SERIALIZED_OBJECT); >> + return json_from_string(json->string); >> +} >> + >> /* Reads the file named 'file_name', parses its contents as a JSON object or >> * array, and returns a newly allocated 'struct json'. The caller must free >> * the returned structure with json_destroy() when it is no longer needed. >> @@ -1563,6 +1593,10 @@ json_serialize(const struct json *json, struct >> json_serializer *s) >> json_serialize_string(json->string, ds); >> break; >> >> + case JSON_SERIALIZED_OBJECT: >> + ds_put_cstr(ds, json->string); >> + break; >> + >> case JSON_N_TYPES: >> default: >> OVS_NOT_REACHED(); >> -- >> 2.31.1 >> > > Thanks Ilya. Shall we add some test cases for the JSON_SERIALIZD_OBJECT in > tests/json.at <http://json.at>?
Having specialized unit tests is a good thing, you're right. For now the functionality is covered by ovsdb tests, since it's used in ovsdb monitor and raft communication, so it's not a big concern that we don't have specialized unit tests. I'll think about how to write them though. It's a bit tricky since serialized object is not a real JSON object, so we can't re-use existing test code. Added to my to-do list. > > Acked-by: Han Zhou <[email protected] <mailto:[email protected]>> _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
