xref: /aosp_15_r20/system/extras/libjsonpb/README.md (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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