Skip to content

Commit

Permalink
json: Add support for partially serialized json objects.
Browse files Browse the repository at this point in the history
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.

Acked-by: Dumitru Ceara <[email protected]>
Acked-by: Han Zhou <[email protected]>
Signed-off-by: Ilya Maximets <[email protected]>
  • Loading branch information
igsilya committed Aug 31, 2021
1 parent c2fb5bd commit b0bca6f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
9 changes: 7 additions & 2 deletions include/openvswitch/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -70,14 +72,15 @@ struct json {
struct json_array array;
long long int integer;
double real;
char *string;
char *string; /* JSON_STRING or JSON_SERIALIZED_OBJECT. */
};
};

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);

Expand All @@ -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 *);
Expand All @@ -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);

Expand Down
34 changes: 34 additions & 0 deletions lib/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>";
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -362,6 +378,7 @@ json_destroy(struct json *json)
break;

case JSON_STRING:
case JSON_SERIALIZED_OBJECT:
free(json->string);
break;

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit b0bca6f

Please sign in to comment.