You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
4.6 KiB
108 lines
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:
|
|
```c++
|
|
strtoull(value.asString(), 0, 10)
|
|
```
|
|
- 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:
|
|
```c++
|
|
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();
|
|
}
|
|
```
|
|
- `libprotobuf` accepts either `lowerCamelCase` (or `json_name` option if it is
|
|
defined) or the original field name as keys in the input JSON file.
|
|
The test in `libjsonpbverify` explicitly check this case to avoid ambiguity;
|
|
only the original field name (or `json_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 if
|
|
`json_name` is not defined. `lowerCamelCase` supported by `libprotobuf` is
|
|
explicitly disallowed (unless explicitly used in `json_name`). For example,
|
|
in the following Protobuf file, only keys `foo_bar` and `barBaz` 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))`, using `libprotobuf`.
|
|
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](https://developers.google.com/protocol-buffers/docs/proto3#json)
|
|
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`, or `double` in the schema
|
|
- JSON strings are generally `string`s, but if you want to impose more
|
|
restrictions on the string, you can also use `Timestamp`, `bytes`,
|
|
**`float`** or **`double`** (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 use `map<string, T>`.
|
|
- Don't use `Any`; it defeats the purpose of having the schema.
|
|
|
|
## Validating a JSON file against a Protobuf definition
|
|
|
|
Example:
|
|
```c++
|
|
#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")));
|
|
```
|