4.6 KiB
libjsonpbparse
This library provides functions to parse a JSON file to a structured Protobuf message.
At this time of writing, libprotobuf-cpp-full
is at version 3.0.0-beta, and
unknown fields in a JSON file cannot be ignored. Do NOT use this library in
vendor / recovery until libprotobuf-cpp-full
is updated.
Using libjsoncpp
in parser code
Since libjsonpbparse
cannot be used in vendor / recovery processes yet,
libjsoncpp
is used instead. However, there are notable differences in the
logic of libjsoncpp
and libprotobuf
when parsing JSON files.
- There are no implicit string to integer conversion in
libjsoncpp
. Hence:- If the Protobuf schema uses 64-bit integers (
(s|fixed|u|)int64
):- The JSON file must use strings (to pass tests in
libjsonpbverify
) - Parser code (that uses
libjsoncpp
) must explicitly convert strings to integers. Example:strtoull(value.asString(), 0, 10)
- The JSON file must use strings (to pass tests in
- If the Protobuf schema uses special floating point values:
- The JSON file must use strings (e.g.
"NaN"
,"Infinity"
,"-Infinity"
) - Parser code must explicitly handle these cases. Example:
double d; if (value.isNumeric()) { d = value.asDouble(); } else { auto&& s = value.asString(); if (s == "NaN") d = std::numeric_limits<double>::quiet_NaN(); else if (s == "Infinity") d = std::numeric_limits<double>::infinity(); else if (s == "-Infinity") d = -std::numeric_limits<double>::infinity(); }
- The JSON file must use strings (e.g.
- If the Protobuf schema uses 64-bit integers (
libprotobuf
accepts eitherlowerCamelCase
(orjson_name
option if it is defined) or the original field name as keys in the input JSON file. The test inlibjsonpbverify
explicitly check this case to avoid ambiguity; only the original field name (orjson_name
option if it is defined) can be used.
Once libprotobuf
in the source tree is updated to a higher version and
libjsonpbparse
is updated to ignore unknown fields in JSON files, all parsing
code must be converted to use libjsonpbparse
for consistency.
libjsonpbverify
This library provides functions and tests to examine a JSON file and validate it against a Protobuf message definition.
In addition to a validity check that libprotobuf
can convert the JSON file to a
Protobuf message (using libjsonpbparse
), it also checks the following:
- Whether there are fields unknown to the schema. All fields in the JSON file must be well defined in the schema.
- Whether the Protobuf file defines JSON keys clearly. The JSON keys must be
the
json_name
option of a Protobuf field, or name of a Protobuf field ifjson_name
is not defined.lowerCamelCase
supported bylibprotobuf
is explicitly disallowed (unless explicitly used injson_name
). For example, in the following Protobuf file, only keysfoo_bar
andbarBaz
are allowed in the JSON file:message Foo { string foo_bar = 1; string bar_baz = 2 [json_name = "barBaz"]; }
- Whether
json == convert_to_json(convert_to_pb(json))
, usinglibprotobuf
. This imposes additional restrictions including:- Enum values must be present as names (not integer values) in the JSON file.
- 64-bit integers and special floating point values (infinity, NaN) must always be strings.
Defining a JSON schema using Protobuf
Check JSON Mapping before defining a Protobuf object as a JSON schema. In general:
- Use proto3.
libjsonverify
does not support proto2. - JSON booleans should be
bool
. - JSON numbers should be
(s|fixed|u|)int32
,float
, ordouble
in the schema - JSON strings are generally
string
s, but if you want to impose more restrictions on the string, you can also useTimestamp
,bytes
,float
ordouble
(if NaN and infinity are valid values), enumerations, etc.- If a custom enumeration is used, parser code should NOT error when the enumeration value name is unknown, as enumeration definitions may be extended in the future.
- JSON arrays should be repeated fields.
- JSON objects should be a well-defined
message
, unless you have a good reason to usemap<string, T>
. - Don't use
Any
; it defeats the purpose of having the schema.
Validating a JSON file against a Protobuf definition
Example:
#include <jsonpb/verify.h>
using namespace ::android::jsonpb;
std::unique_ptr<JsonSchemaTestConfig> CreateCgroupsParam() {
}
INSTANTIATE_TEST_SUITE_P(LibProcessgroupProto, JsonSchemaTest,
::testing::Values(MakeTestParam<Cgroups>("cgroups.json")));