1*288bf522SAndroid Build Coastguard Worker# `libjsonpbparse` 2*288bf522SAndroid Build Coastguard Worker 3*288bf522SAndroid Build Coastguard WorkerThis library provides functions to parse a JSON file to a structured Protobuf 4*288bf522SAndroid Build Coastguard Workermessage. 5*288bf522SAndroid Build Coastguard Worker 6*288bf522SAndroid Build Coastguard WorkerAt this time of writing, `libprotobuf-cpp-full` is at version 3.0.0-beta, and 7*288bf522SAndroid Build Coastguard Workerunknown fields in a JSON file cannot be ignored. Do **NOT** use this library in 8*288bf522SAndroid Build Coastguard Workervendor / recovery until `libprotobuf-cpp-full` is updated. 9*288bf522SAndroid Build Coastguard Worker 10*288bf522SAndroid Build Coastguard Worker## Using `libjsoncpp` in parser code 11*288bf522SAndroid Build Coastguard Worker 12*288bf522SAndroid Build Coastguard WorkerSince `libjsonpbparse` cannot be used in vendor / recovery processes yet, 13*288bf522SAndroid Build Coastguard Worker`libjsoncpp` is used instead. However, there are notable differences in the 14*288bf522SAndroid Build Coastguard Workerlogic of `libjsoncpp` and `libprotobuf` when parsing JSON files. 15*288bf522SAndroid Build Coastguard Worker 16*288bf522SAndroid Build Coastguard Worker- There are no implicit string to integer conversion in `libjsoncpp`. Hence: 17*288bf522SAndroid Build Coastguard Worker - If the Protobuf schema uses 64-bit integers (`(s|fixed|u|)int64`): 18*288bf522SAndroid Build Coastguard Worker - The JSON file must use strings (to pass tests in `libjsonpbverify`) 19*288bf522SAndroid Build Coastguard Worker - Parser code (that uses `libjsoncpp`) must explicitly convert strings to 20*288bf522SAndroid Build Coastguard Worker integers. Example: 21*288bf522SAndroid Build Coastguard Worker ```c++ 22*288bf522SAndroid Build Coastguard Worker strtoull(value.asString(), 0, 10) 23*288bf522SAndroid Build Coastguard Worker ``` 24*288bf522SAndroid Build Coastguard Worker - If the Protobuf schema uses special floating point values: 25*288bf522SAndroid Build Coastguard Worker - The JSON file must use strings (e.g. `"NaN"`, `"Infinity"`, `"-Infinity"`) 26*288bf522SAndroid Build Coastguard Worker - Parser code must explicitly handle these cases. Example: 27*288bf522SAndroid Build Coastguard Worker ```c++ 28*288bf522SAndroid Build Coastguard Worker double d; 29*288bf522SAndroid Build Coastguard Worker if (value.isNumeric()) { 30*288bf522SAndroid Build Coastguard Worker d = value.asDouble(); 31*288bf522SAndroid Build Coastguard Worker } else { 32*288bf522SAndroid Build Coastguard Worker auto&& s = value.asString(); 33*288bf522SAndroid Build Coastguard Worker if (s == "NaN") d = std::numeric_limits<double>::quiet_NaN(); 34*288bf522SAndroid Build Coastguard Worker else if (s == "Infinity") d = std::numeric_limits<double>::infinity(); 35*288bf522SAndroid Build Coastguard Worker else if (s == "-Infinity") d = -std::numeric_limits<double>::infinity(); 36*288bf522SAndroid Build Coastguard Worker } 37*288bf522SAndroid Build Coastguard Worker ``` 38*288bf522SAndroid Build Coastguard Worker- `libprotobuf` accepts either `lowerCamelCase` (or `json_name` option if it is 39*288bf522SAndroid Build Coastguard Worker defined) or the original field name as keys in the input JSON file. 40*288bf522SAndroid Build Coastguard Worker The test in `libjsonpbverify` explicitly check this case to avoid ambiguity; 41*288bf522SAndroid Build Coastguard Worker only the original field name (or `json_name` option if it is defined) can be 42*288bf522SAndroid Build Coastguard Worker used. 43*288bf522SAndroid Build Coastguard Worker 44*288bf522SAndroid Build Coastguard WorkerOnce `libprotobuf` in the source tree is updated to a higher version and 45*288bf522SAndroid Build Coastguard Worker`libjsonpbparse` is updated to ignore unknown fields in JSON files, all parsing 46*288bf522SAndroid Build Coastguard Workercode must be converted to use `libjsonpbparse` for consistency. 47*288bf522SAndroid Build Coastguard Worker 48*288bf522SAndroid Build Coastguard Worker# `libjsonpbverify` 49*288bf522SAndroid Build Coastguard Worker 50*288bf522SAndroid Build Coastguard WorkerThis library provides functions and tests to examine a JSON file and validate 51*288bf522SAndroid Build Coastguard Workerit against a Protobuf message definition. 52*288bf522SAndroid Build Coastguard Worker 53*288bf522SAndroid Build Coastguard WorkerIn addition to a validity check that `libprotobuf` can convert the JSON file to a 54*288bf522SAndroid Build Coastguard WorkerProtobuf message (using `libjsonpbparse`), it also checks the following: 55*288bf522SAndroid Build Coastguard Worker 56*288bf522SAndroid Build Coastguard Worker- Whether there are fields unknown to the schema. All fields in the JSON file 57*288bf522SAndroid Build Coastguard Worker must be well defined in the schema. 58*288bf522SAndroid Build Coastguard Worker- Whether the Protobuf file defines JSON keys clearly. The JSON keys must be 59*288bf522SAndroid Build Coastguard Worker the `json_name` option of a Protobuf field, or name of a Protobuf field if 60*288bf522SAndroid Build Coastguard Worker `json_name` is not defined. `lowerCamelCase` supported by `libprotobuf` is 61*288bf522SAndroid Build Coastguard Worker explicitly disallowed (unless explicitly used in `json_name`). For example, 62*288bf522SAndroid Build Coastguard Worker in the following Protobuf file, only keys `foo_bar` and `barBaz` are allowed 63*288bf522SAndroid Build Coastguard Worker in the JSON file: 64*288bf522SAndroid Build Coastguard Worker ``` 65*288bf522SAndroid Build Coastguard Worker message Foo { 66*288bf522SAndroid Build Coastguard Worker string foo_bar = 1; 67*288bf522SAndroid Build Coastguard Worker string bar_baz = 2 [json_name = "barBaz"]; 68*288bf522SAndroid Build Coastguard Worker } 69*288bf522SAndroid Build Coastguard Worker ``` 70*288bf522SAndroid Build Coastguard Worker- Whether `json == convert_to_json(convert_to_pb(json))`, using `libprotobuf`. 71*288bf522SAndroid Build Coastguard Worker This imposes additional restrictions including: 72*288bf522SAndroid Build Coastguard Worker - Enum values must be present as names (not integer values) in the JSON file. 73*288bf522SAndroid Build Coastguard Worker - 64-bit integers and special floating point values (infinity, NaN) must 74*288bf522SAndroid Build Coastguard Worker always be strings. 75*288bf522SAndroid Build Coastguard Worker 76*288bf522SAndroid Build Coastguard Worker## Defining a JSON schema using Protobuf 77*288bf522SAndroid Build Coastguard Worker 78*288bf522SAndroid Build Coastguard WorkerCheck [JSON Mapping](https://developers.google.com/protocol-buffers/docs/proto3#json) 79*288bf522SAndroid Build Coastguard Workerbefore defining a Protobuf object as a JSON schema. In general: 80*288bf522SAndroid Build Coastguard Worker 81*288bf522SAndroid Build Coastguard Worker- **Use proto3**. `libjsonverify` does not support proto2. 82*288bf522SAndroid Build Coastguard Worker- JSON booleans should be `bool`. 83*288bf522SAndroid Build Coastguard Worker- JSON numbers should be `(s|fixed|u|)int32`, `float`, or `double` in the schema 84*288bf522SAndroid Build Coastguard Worker- JSON strings are generally `string`s, but if you want to impose more 85*288bf522SAndroid Build Coastguard Worker restrictions on the string, you can also use `Timestamp`, `bytes`, 86*288bf522SAndroid Build Coastguard Worker **`float`** or **`double`** (if NaN and infinity are valid values), 87*288bf522SAndroid Build Coastguard Worker enumerations, etc. 88*288bf522SAndroid Build Coastguard Worker - If a custom enumeration is used, parser code should **NOT** error when the 89*288bf522SAndroid Build Coastguard Worker enumeration value name is unknown, as enumeration definitions may be 90*288bf522SAndroid Build Coastguard Worker extended in the future. 91*288bf522SAndroid Build Coastguard Worker- JSON arrays should be repeated fields. 92*288bf522SAndroid Build Coastguard Worker- JSON objects should be a well-defined `message`, unless you have a good reason 93*288bf522SAndroid Build Coastguard Worker to use `map<string, T>`. 94*288bf522SAndroid Build Coastguard Worker- Don't use `Any`; it defeats the purpose of having the schema. 95*288bf522SAndroid Build Coastguard Worker 96*288bf522SAndroid Build Coastguard Worker## Validating a JSON file against a Protobuf definition 97*288bf522SAndroid Build Coastguard Worker 98*288bf522SAndroid Build Coastguard WorkerExample: 99*288bf522SAndroid Build Coastguard Worker```c++ 100*288bf522SAndroid Build Coastguard Worker#include <jsonpb/verify.h> 101*288bf522SAndroid Build Coastguard Workerusing namespace ::android::jsonpb; 102*288bf522SAndroid Build Coastguard Workerstd::unique_ptr<JsonSchemaTestConfig> CreateCgroupsParam() { 103*288bf522SAndroid Build Coastguard Worker 104*288bf522SAndroid Build Coastguard Worker} 105*288bf522SAndroid Build Coastguard WorkerINSTANTIATE_TEST_SUITE_P(LibProcessgroupProto, JsonSchemaTest, 106*288bf522SAndroid Build Coastguard Worker ::testing::Values(MakeTestParam<Cgroups>("cgroups.json"))); 107*288bf522SAndroid Build Coastguard Worker``` 108