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