1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/json/json_value_converter.h"
6
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <string_view>
11 #include <vector>
12
13 #include "base/json/json_reader.h"
14 #include "base/values.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace base {
18 namespace {
19
20 // Very simple messages.
21 struct SimpleMessage {
22 enum SimpleEnum {
23 FOO,
24 BAR,
25 };
26 int foo;
27 std::string bar;
28 bool baz;
29 bool bstruct;
30 SimpleEnum simple_enum;
31 std::vector<std::unique_ptr<int>> ints;
32 std::vector<std::unique_ptr<std::string>> string_values;
SimpleMessagebase::__anonec408df40111::SimpleMessage33 SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
34
ParseSimpleEnumbase::__anonec408df40111::SimpleMessage35 static bool ParseSimpleEnum(std::string_view value, SimpleEnum* field) {
36 if (value == "foo") {
37 *field = FOO;
38 return true;
39 }
40 if (value == "bar") {
41 *field = BAR;
42 return true;
43 }
44 return false;
45 }
46
HasFieldPresentbase::__anonec408df40111::SimpleMessage47 static bool HasFieldPresent(const base::Value* value, bool* result) {
48 *result = value != nullptr;
49 return true;
50 }
51
GetValueStringbase::__anonec408df40111::SimpleMessage52 static bool GetValueString(const base::Value* value, std::string* result) {
53 const Value::Dict* dict = value->GetIfDict();
54 if (!dict)
55 return false;
56 const std::string* str = dict->FindString("val");
57 if (!str)
58 return false;
59 if (result)
60 *result = *str;
61 return true;
62 }
63
RegisterJSONConverterbase::__anonec408df40111::SimpleMessage64 static void RegisterJSONConverter(
65 base::JSONValueConverter<SimpleMessage>* converter) {
66 converter->RegisterIntField("foo", &SimpleMessage::foo);
67 converter->RegisterStringField("bar", &SimpleMessage::bar);
68 converter->RegisterBoolField("baz", &SimpleMessage::baz);
69 converter->RegisterCustomField<SimpleEnum>(
70 "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
71 converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
72 converter->RegisterCustomValueField<bool>(
73 "bstruct", &SimpleMessage::bstruct, &HasFieldPresent);
74 converter->RegisterRepeatedCustomValue<std::string>(
75 "string_values", &SimpleMessage::string_values, &GetValueString);
76 }
77 };
78
79 // For nested messages.
80 struct NestedMessage {
81 double foo;
82 SimpleMessage child;
83 std::vector<std::unique_ptr<SimpleMessage>> children;
84
NestedMessagebase::__anonec408df40111::NestedMessage85 NestedMessage() : foo(0) {}
86
RegisterJSONConverterbase::__anonec408df40111::NestedMessage87 static void RegisterJSONConverter(
88 base::JSONValueConverter<NestedMessage>* converter) {
89 converter->RegisterDoubleField("foo", &NestedMessage::foo);
90 converter->RegisterNestedField("child", &NestedMessage::child);
91 converter->RegisterRepeatedMessage("children", &NestedMessage::children);
92 }
93 };
94
95 } // namespace
96
TEST(JSONValueConverterTest,ParseSimpleMessage)97 TEST(JSONValueConverterTest, ParseSimpleMessage) {
98 const char normal_data[] =
99 "{\n"
100 " \"foo\": 1,\n"
101 " \"bar\": \"bar\",\n"
102 " \"baz\": true,\n"
103 " \"bstruct\": {},\n"
104 " \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
105 " \"simple_enum\": \"foo\","
106 " \"ints\": [1, 2]"
107 "}\n";
108
109 std::optional<Value> value = base::JSONReader::Read(normal_data);
110 ASSERT_TRUE(value);
111 SimpleMessage message;
112 base::JSONValueConverter<SimpleMessage> converter;
113 EXPECT_TRUE(converter.Convert(*value, &message));
114
115 EXPECT_EQ(1, message.foo);
116 EXPECT_EQ("bar", message.bar);
117 EXPECT_TRUE(message.baz);
118 EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
119 EXPECT_EQ(2, static_cast<int>(message.ints.size()));
120 ASSERT_EQ(2U, message.string_values.size());
121 EXPECT_EQ("value_1", *message.string_values[0]);
122 EXPECT_EQ("value_2", *message.string_values[1]);
123 EXPECT_EQ(1, *(message.ints[0]));
124 EXPECT_EQ(2, *(message.ints[1]));
125 }
126
TEST(JSONValueConverterTest,ParseNestedMessage)127 TEST(JSONValueConverterTest, ParseNestedMessage) {
128 const char normal_data[] =
129 "{\n"
130 " \"foo\": 1.0,\n"
131 " \"child\": {\n"
132 " \"foo\": 1,\n"
133 " \"bar\": \"bar\",\n"
134 " \"bstruct\": {},\n"
135 " \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
136 " \"baz\": true\n"
137 " },\n"
138 " \"children\": [{\n"
139 " \"foo\": 2,\n"
140 " \"bar\": \"foobar\",\n"
141 " \"bstruct\": \"\",\n"
142 " \"string_values\": [{\"val\": \"value_1\"}],"
143 " \"baz\": true\n"
144 " },\n"
145 " {\n"
146 " \"foo\": 3,\n"
147 " \"bar\": \"barbaz\",\n"
148 " \"baz\": false\n"
149 " }]\n"
150 "}\n";
151
152 std::optional<Value> value = base::JSONReader::Read(normal_data);
153 ASSERT_TRUE(value);
154 NestedMessage message;
155 base::JSONValueConverter<NestedMessage> converter;
156 EXPECT_TRUE(converter.Convert(*value, &message));
157
158 EXPECT_EQ(1.0, message.foo);
159 EXPECT_EQ(1, message.child.foo);
160 EXPECT_EQ("bar", message.child.bar);
161 EXPECT_TRUE(message.child.baz);
162 EXPECT_TRUE(message.child.bstruct);
163 ASSERT_EQ(2U, message.child.string_values.size());
164 EXPECT_EQ("value_1", *message.child.string_values[0]);
165 EXPECT_EQ("value_2", *message.child.string_values[1]);
166
167 EXPECT_EQ(2, static_cast<int>(message.children.size()));
168 const SimpleMessage* first_child = message.children[0].get();
169 ASSERT_TRUE(first_child);
170 EXPECT_EQ(2, first_child->foo);
171 EXPECT_EQ("foobar", first_child->bar);
172 EXPECT_TRUE(first_child->baz);
173 EXPECT_TRUE(first_child->bstruct);
174 ASSERT_EQ(1U, first_child->string_values.size());
175 EXPECT_EQ("value_1", *first_child->string_values[0]);
176
177 const SimpleMessage* second_child = message.children[1].get();
178 ASSERT_TRUE(second_child);
179 EXPECT_EQ(3, second_child->foo);
180 EXPECT_EQ("barbaz", second_child->bar);
181 EXPECT_FALSE(second_child->baz);
182 EXPECT_FALSE(second_child->bstruct);
183 EXPECT_EQ(0U, second_child->string_values.size());
184 }
185
TEST(JSONValueConverterTest,ParseFailures)186 TEST(JSONValueConverterTest, ParseFailures) {
187 const char normal_data[] =
188 "{\n"
189 " \"foo\": 1,\n"
190 " \"bar\": 2,\n" // "bar" is an integer here.
191 " \"baz\": true,\n"
192 " \"ints\": [1, 2]"
193 "}\n";
194
195 std::optional<Value> value = base::JSONReader::Read(normal_data);
196 ASSERT_TRUE(value);
197 SimpleMessage message;
198 base::JSONValueConverter<SimpleMessage> converter;
199 EXPECT_FALSE(converter.Convert(*value, &message));
200 // Do not check the values below. |message| may be modified during
201 // Convert() even it fails.
202 }
203
TEST(JSONValueConverterTest,ParseWithMissingFields)204 TEST(JSONValueConverterTest, ParseWithMissingFields) {
205 const char normal_data[] =
206 "{\n"
207 " \"foo\": 1,\n"
208 " \"baz\": true,\n"
209 " \"ints\": [1, 2]"
210 "}\n";
211
212 std::optional<Value> value = base::JSONReader::Read(normal_data);
213 ASSERT_TRUE(value);
214 SimpleMessage message;
215 base::JSONValueConverter<SimpleMessage> converter;
216 // Convert() still succeeds even if the input doesn't have "bar" field.
217 EXPECT_TRUE(converter.Convert(*value, &message));
218
219 EXPECT_EQ(1, message.foo);
220 EXPECT_TRUE(message.baz);
221 EXPECT_EQ(2, static_cast<int>(message.ints.size()));
222 EXPECT_EQ(1, *(message.ints[0]));
223 EXPECT_EQ(2, *(message.ints[1]));
224 }
225
TEST(JSONValueConverterTest,EnumParserFails)226 TEST(JSONValueConverterTest, EnumParserFails) {
227 const char normal_data[] =
228 "{\n"
229 " \"foo\": 1,\n"
230 " \"bar\": \"bar\",\n"
231 " \"baz\": true,\n"
232 " \"simple_enum\": \"baz\","
233 " \"ints\": [1, 2]"
234 "}\n";
235
236 std::optional<Value> value = base::JSONReader::Read(normal_data);
237 ASSERT_TRUE(value);
238 SimpleMessage message;
239 base::JSONValueConverter<SimpleMessage> converter;
240 EXPECT_FALSE(converter.Convert(*value, &message));
241 // No check the values as mentioned above.
242 }
243
TEST(JSONValueConverterTest,RepeatedValueErrorInTheMiddle)244 TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
245 const char normal_data[] =
246 "{\n"
247 " \"foo\": 1,\n"
248 " \"bar\": \"bar\",\n"
249 " \"baz\": true,\n"
250 " \"simple_enum\": \"baz\","
251 " \"ints\": [1, false]"
252 "}\n";
253
254 std::optional<Value> value = base::JSONReader::Read(normal_data);
255 ASSERT_TRUE(value);
256 SimpleMessage message;
257 base::JSONValueConverter<SimpleMessage> converter;
258 EXPECT_FALSE(converter.Convert(*value, &message));
259 // No check the values as mentioned above.
260 }
261
262 } // namespace base
263