xref: /aosp_15_r20/system/extras/libjsonpb/verify/include/jsonpb/verify.h (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #pragma once
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <sstream>
20*288bf522SAndroid Build Coastguard Worker #include <string>
21*288bf522SAndroid Build Coastguard Worker #include <vector>
22*288bf522SAndroid Build Coastguard Worker 
23*288bf522SAndroid Build Coastguard Worker #include <google/protobuf/message.h>
24*288bf522SAndroid Build Coastguard Worker #include <json/reader.h>
25*288bf522SAndroid Build Coastguard Worker #include <json/value.h>
26*288bf522SAndroid Build Coastguard Worker #include <jsonpb/jsonpb.h>
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker namespace android {
29*288bf522SAndroid Build Coastguard Worker namespace jsonpb {
30*288bf522SAndroid Build Coastguard Worker 
31*288bf522SAndroid Build Coastguard Worker // Ensure that the JSON file has no unknown fields that is not defined in proto.
32*288bf522SAndroid Build Coastguard Worker // Because we want forwards compatibility, the parser of JSON files must ignore
33*288bf522SAndroid Build Coastguard Worker // unknown fields. This is achievable with libprotobuf version > 3.0-beta.
34*288bf522SAndroid Build Coastguard Worker // - <= 3.0-beta: we have to check unknown fields manually, and parser cannot
35*288bf522SAndroid Build Coastguard Worker // use libprotobuf
36*288bf522SAndroid Build Coastguard Worker //   to parse JSON files.
37*288bf522SAndroid Build Coastguard Worker // - < 3.5: libprotobuf discards all unknown fields. We can still check unknown
38*288bf522SAndroid Build Coastguard Worker // fields manually, but
39*288bf522SAndroid Build Coastguard Worker //   an easier way to check is `json == FormatJson(json)` (schematically)
40*288bf522SAndroid Build Coastguard Worker // - >= 3.5: Unknown fields are preserved, so FormatJson() may contain these
41*288bf522SAndroid Build Coastguard Worker // unknown fields. We can
42*288bf522SAndroid Build Coastguard Worker //   still check fields manually, or use reflection mechanism.
43*288bf522SAndroid Build Coastguard Worker //
44*288bf522SAndroid Build Coastguard Worker // For example, if a new field "foo" is added to cgroups.json but not to
45*288bf522SAndroid Build Coastguard Worker // cgroups.proto, libprocessgroup could technically read the value of "foo" by
46*288bf522SAndroid Build Coastguard Worker // using other libraries that parse JSON strings, effectively working around the
47*288bf522SAndroid Build Coastguard Worker // schema.
48*288bf522SAndroid Build Coastguard Worker //
49*288bf522SAndroid Build Coastguard Worker // This test also ensures that the parser does not use alternative key names.
50*288bf522SAndroid Build Coastguard Worker // For example, if the proto file states: message Foo { string foo_bar = 1;
51*288bf522SAndroid Build Coastguard Worker // string bar_baz = 2 [json_name = "BarBaz"]; } Then the parser accepts
52*288bf522SAndroid Build Coastguard Worker // "foo_bar" "fooBar", "bar_baz", "BarBaz" as valid key names. Here, we enforce
53*288bf522SAndroid Build Coastguard Worker // that the JSON file must use "foo_bar" and "BarBaz".
54*288bf522SAndroid Build Coastguard Worker //
55*288bf522SAndroid Build Coastguard Worker // Requiring this avoids surprises like:
56*288bf522SAndroid Build Coastguard Worker //     message Foo { string FooBar = 1; }
57*288bf522SAndroid Build Coastguard Worker //     { "fooBar" : "s" }
58*288bf522SAndroid Build Coastguard Worker // conforms with the schema, because libprotobuf accept "fooBar" as a valid key.
59*288bf522SAndroid Build Coastguard Worker // The correct schema should be:
60*288bf522SAndroid Build Coastguard Worker //     message Foo { string foo_bar = 1 [json_name="fooBar"]; }
61*288bf522SAndroid Build Coastguard Worker //
62*288bf522SAndroid Build Coastguard Worker // Params:
63*288bf522SAndroid Build Coastguard Worker //    path: path to navigate inside JSON tree. For example, {"foo", "bar"} for
64*288bf522SAndroid Build Coastguard Worker //    the value "string" in
65*288bf522SAndroid Build Coastguard Worker //          {"foo": {"bar" : "string"}}
66*288bf522SAndroid Build Coastguard Worker bool AllFieldsAreKnown(const google::protobuf::Message& message, const std::string& json,
67*288bf522SAndroid Build Coastguard Worker                        std::string* error);
68*288bf522SAndroid Build Coastguard Worker 
69*288bf522SAndroid Build Coastguard Worker // Format the given JSON string according to Prototype T. This will serialize
70*288bf522SAndroid Build Coastguard Worker // the JSON string to a Prototype message, then re-print the message as JSON. By
71*288bf522SAndroid Build Coastguard Worker // reformatting the JSON string, we effectively enforces that the JSON source
72*288bf522SAndroid Build Coastguard Worker // file uses conventions of Protobuf's JSON writer; e.g. 64-bit integers /
73*288bf522SAndroid Build Coastguard Worker // special floating point numbers (inf, NaN, etc.) in strings, enum values in
74*288bf522SAndroid Build Coastguard Worker // names, etc.
75*288bf522SAndroid Build Coastguard Worker //
76*288bf522SAndroid Build Coastguard Worker // Params:
77*288bf522SAndroid Build Coastguard Worker //   scratch_space: The scratch space to use to store the Protobuf message. It
78*288bf522SAndroid Build Coastguard Worker //   must be a pointer
79*288bf522SAndroid Build Coastguard Worker //                  to the schema that the JSON string conforms to.
80*288bf522SAndroid Build Coastguard Worker bool EqReformattedJson(const std::string& json, google::protobuf::Message* scratch_space,
81*288bf522SAndroid Build Coastguard Worker                        std::string* error);
82*288bf522SAndroid Build Coastguard Worker 
83*288bf522SAndroid Build Coastguard Worker namespace internal {
84*288bf522SAndroid Build Coastguard Worker // See EqReformattedJson().
85*288bf522SAndroid Build Coastguard Worker ErrorOr<std::string> FormatJson(const std::string& json, google::protobuf::Message* scratch_space);
86*288bf522SAndroid Build Coastguard Worker 
87*288bf522SAndroid Build Coastguard Worker }  // namespace internal
88*288bf522SAndroid Build Coastguard Worker 
89*288bf522SAndroid Build Coastguard Worker }  // namespace jsonpb
90*288bf522SAndroid Build Coastguard Worker }  // namespace android
91