On Tue, Aug 24, 2021 at 12:00 PM Ilya Maximets <[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]>
> ---
>  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?

Acked-by: Han Zhou <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to