blob: 4cca034f3320395127b9e7698b3f2b3cec416785 [file] [log] [blame]
[email protected]261c877e2012-01-05 09:46:421// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]193f946b2011-12-22 18:31:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
6#define BASE_JSON_JSON_VALUE_CONVERTER_H_
[email protected]193f946b2011-12-22 18:31:477
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9
dcheng093de9b2016-04-04 21:25:5110#include <memory>
[email protected]193f946b2011-12-22 18:31:4711#include <string>
12#include <vector>
13
dmichael7d09007e2014-12-18 22:30:1114#include "base/base_export.h"
[email protected]193f946b2011-12-22 18:31:4715#include "base/logging.h"
avi9b6f42932015-12-26 22:15:1416#include "base/macros.h"
[email protected]a9b8e0a2012-01-14 05:36:1217#include "base/memory/scoped_vector.h"
[email protected]193f946b2011-12-22 18:31:4718#include "base/stl_util.h"
[email protected]d529cb02013-06-10 19:06:5719#include "base/strings/string16.h"
[email protected]eb62f7262013-03-30 14:29:0020#include "base/strings/string_piece.h"
[email protected]193f946b2011-12-22 18:31:4721#include "base/values.h"
22
23// JSONValueConverter converts a JSON value into a C++ struct in a
24// lightweight way.
25//
26// Usage:
27// For real examples, you may want to refer to _unittest.cc file.
28//
29// Assume that you have a struct like this:
30// struct Message {
31// int foo;
32// std::string bar;
33// static void RegisterJSONConverter(
34// JSONValueConverter<Message>* converter);
35// };
36//
37// And you want to parse a json data into this struct. First, you
38// need to declare RegisterJSONConverter() method in your struct.
39// // static
40// void Message::RegisterJSONConverter(
41// JSONValueConverter<Message>* converter) {
42// converter->RegisterIntField("foo", &Message::foo);
43// converter->RegisterStringField("bar", &Message::bar);
44// }
45//
46// Then, you just instantiate your JSONValueConverter of your type and call
47// Convert() method.
48// Message message;
49// JSONValueConverter<Message> converter;
50// converter.Convert(json, &message);
51//
[email protected]261c877e2012-01-05 09:46:4252// Convert() returns false when it fails. Here "fail" means that the value is
53// structurally different from expected, such like a string value appears
54// for an int field. Do not report failures for missing fields.
55// Also note that Convert() will modify the passed |message| even when it
56// fails for performance reason.
57//
[email protected]193f946b2011-12-22 18:31:4758// For nested field, the internal message also has to implement the registration
59// method. Then, just use RegisterNestedField() from the containing struct's
60// RegisterJSONConverter method.
61// struct Nested {
62// Message foo;
[email protected]261c877e2012-01-05 09:46:4263// static void RegisterJSONConverter(...) {
[email protected]193f946b2011-12-22 18:31:4764// ...
65// converter->RegisterNestedField("foo", &Nested::foo);
66// }
67// };
68//
[email protected]a9b8e0a2012-01-14 05:36:1269// For repeated field, we just assume ScopedVector for its container
[email protected]193f946b2011-12-22 18:31:4770// and you can put RegisterRepeatedInt or some other types. Use
71// RegisterRepeatedMessage for nested repeated fields.
72//
[email protected]6009ca92012-01-13 02:18:0273// Sometimes JSON format uses string representations for other types such
74// like enum, timestamp, or URL. You can use RegisterCustomField method
75// and specify a function to convert a StringPiece to your type.
76// bool ConvertFunc(const StringPiece& s, YourEnum* result) {
77// // do something and return true if succeed...
78// }
79// struct Message {
80// YourEnum ye;
81// ...
82// static void RegisterJSONConverter(...) {
83// ...
84// converter->RegsiterCustomField<YourEnum>(
85// "your_enum", &Message::ye, &ConvertFunc);
86// }
87// };
[email protected]193f946b2011-12-22 18:31:4788
89namespace base {
90
91template <typename StructType>
92class JSONValueConverter;
93
94namespace internal {
95
[email protected]983b9b72012-01-27 07:12:2196template<typename StructType>
[email protected]193f946b2011-12-22 18:31:4797class FieldConverterBase {
98 public:
[email protected]983b9b72012-01-27 07:12:2199 explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
100 virtual ~FieldConverterBase() {}
101 virtual bool ConvertField(const base::Value& value, StructType* obj)
102 const = 0;
[email protected]193f946b2011-12-22 18:31:47103 const std::string& field_path() const { return field_path_; }
104
105 private:
106 std::string field_path_;
107 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
108};
109
110template <typename FieldType>
111class ValueConverter {
112 public:
113 virtual ~ValueConverter() {}
[email protected]261c877e2012-01-05 09:46:42114 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
[email protected]193f946b2011-12-22 18:31:47115};
116
117template <typename StructType, typename FieldType>
[email protected]983b9b72012-01-27 07:12:21118class FieldConverter : public FieldConverterBase<StructType> {
[email protected]193f946b2011-12-22 18:31:47119 public:
120 explicit FieldConverter(const std::string& path,
121 FieldType StructType::* field,
122 ValueConverter<FieldType>* converter)
[email protected]983b9b72012-01-27 07:12:21123 : FieldConverterBase<StructType>(path),
[email protected]193f946b2011-12-22 18:31:47124 field_pointer_(field),
125 value_converter_(converter) {
126 }
127
nickc0b001062015-04-22 23:17:20128 bool ConvertField(const base::Value& value, StructType* dst) const override {
[email protected]261c877e2012-01-05 09:46:42129 return value_converter_->Convert(value, &(dst->*field_pointer_));
[email protected]193f946b2011-12-22 18:31:47130 }
131
132 private:
133 FieldType StructType::* field_pointer_;
dcheng093de9b2016-04-04 21:25:51134 std::unique_ptr<ValueConverter<FieldType>> value_converter_;
[email protected]193f946b2011-12-22 18:31:47135 DISALLOW_COPY_AND_ASSIGN(FieldConverter);
136};
137
138template <typename FieldType>
139class BasicValueConverter;
140
141template <>
dmichael7d09007e2014-12-18 22:30:11142class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
[email protected]193f946b2011-12-22 18:31:47143 public:
144 BasicValueConverter() {}
145
dmichael7d09007e2014-12-18 22:30:11146 bool Convert(const base::Value& value, int* field) const override;
[email protected]193f946b2011-12-22 18:31:47147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
150};
151
152template <>
dmichael7d09007e2014-12-18 22:30:11153class BASE_EXPORT BasicValueConverter<std::string>
154 : public ValueConverter<std::string> {
[email protected]193f946b2011-12-22 18:31:47155 public:
156 BasicValueConverter() {}
157
dmichael7d09007e2014-12-18 22:30:11158 bool Convert(const base::Value& value, std::string* field) const override;
[email protected]261c877e2012-01-05 09:46:42159
160 private:
161 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
162};
163
164template <>
dmichael7d09007e2014-12-18 22:30:11165class BASE_EXPORT BasicValueConverter<string16>
166 : public ValueConverter<string16> {
[email protected]261c877e2012-01-05 09:46:42167 public:
168 BasicValueConverter() {}
169
dmichael7d09007e2014-12-18 22:30:11170 bool Convert(const base::Value& value, string16* field) const override;
[email protected]193f946b2011-12-22 18:31:47171
172 private:
173 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
174};
175
176template <>
dmichael7d09007e2014-12-18 22:30:11177class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
[email protected]193f946b2011-12-22 18:31:47178 public:
179 BasicValueConverter() {}
180
dmichael7d09007e2014-12-18 22:30:11181 bool Convert(const base::Value& value, double* field) const override;
[email protected]193f946b2011-12-22 18:31:47182
183 private:
184 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
185};
186
187template <>
dmichael7d09007e2014-12-18 22:30:11188class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
[email protected]193f946b2011-12-22 18:31:47189 public:
190 BasicValueConverter() {}
191
dmichael7d09007e2014-12-18 22:30:11192 bool Convert(const base::Value& value, bool* field) const override;
[email protected]193f946b2011-12-22 18:31:47193
194 private:
195 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
196};
197
[email protected]6009ca92012-01-13 02:18:02198template <typename FieldType>
[email protected]038cf352012-04-13 00:14:15199class ValueFieldConverter : public ValueConverter<FieldType> {
200 public:
201 typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
202
203 ValueFieldConverter(ConvertFunc convert_func)
204 : convert_func_(convert_func) {}
205
nickc0b001062015-04-22 23:17:20206 bool Convert(const base::Value& value, FieldType* field) const override {
[email protected]038cf352012-04-13 00:14:15207 return convert_func_(&value, field);
208 }
209
210 private:
211 ConvertFunc convert_func_;
212
213 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
214};
215
216template <typename FieldType>
[email protected]6009ca92012-01-13 02:18:02217class CustomFieldConverter : public ValueConverter<FieldType> {
218 public:
219 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
220
221 CustomFieldConverter(ConvertFunc convert_func)
222 : convert_func_(convert_func) {}
223
nickc0b001062015-04-22 23:17:20224 bool Convert(const base::Value& value, FieldType* field) const override {
[email protected]6009ca92012-01-13 02:18:02225 std::string string_value;
226 return value.GetAsString(&string_value) &&
227 convert_func_(string_value, field);
228 }
229
230 private:
231 ConvertFunc convert_func_;
232
233 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
234};
235
[email protected]193f946b2011-12-22 18:31:47236template <typename NestedType>
237class NestedValueConverter : public ValueConverter<NestedType> {
238 public:
239 NestedValueConverter() {}
240
nickc0b001062015-04-22 23:17:20241 bool Convert(const base::Value& value, NestedType* field) const override {
[email protected]261c877e2012-01-05 09:46:42242 return converter_.Convert(value, field);
[email protected]193f946b2011-12-22 18:31:47243 }
244
245 private:
246 JSONValueConverter<NestedType> converter_;
247 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
248};
249
250template <typename Element>
[email protected]a9b8e0a2012-01-14 05:36:12251class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
[email protected]193f946b2011-12-22 18:31:47252 public:
253 RepeatedValueConverter() {}
254
nickc0b001062015-04-22 23:17:20255 bool Convert(const base::Value& value,
256 ScopedVector<Element>* field) const override {
[email protected]193f946b2011-12-22 18:31:47257 const base::ListValue* list = NULL;
258 if (!value.GetAsList(&list)) {
259 // The field is not a list.
[email protected]261c877e2012-01-05 09:46:42260 return false;
[email protected]193f946b2011-12-22 18:31:47261 }
262
263 field->reserve(list->GetSize());
264 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37265 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47266 if (!list->Get(i, &element))
267 continue;
268
dcheng093de9b2016-04-04 21:25:51269 std::unique_ptr<Element> e(new Element);
[email protected]50fa6f922012-01-26 19:32:36270 if (basic_converter_.Convert(*element, e.get())) {
271 field->push_back(e.release());
[email protected]a9b8e0a2012-01-14 05:36:12272 } else {
[email protected]261c877e2012-01-05 09:46:42273 DVLOG(1) << "failure at " << i << "-th element";
274 return false;
275 }
[email protected]193f946b2011-12-22 18:31:47276 }
[email protected]261c877e2012-01-05 09:46:42277 return true;
[email protected]193f946b2011-12-22 18:31:47278 }
279
280 private:
281 BasicValueConverter<Element> basic_converter_;
282 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
283};
284
285template <typename NestedType>
286class RepeatedMessageConverter
[email protected]a9b8e0a2012-01-14 05:36:12287 : public ValueConverter<ScopedVector<NestedType> > {
[email protected]193f946b2011-12-22 18:31:47288 public:
289 RepeatedMessageConverter() {}
290
nickc0b001062015-04-22 23:17:20291 bool Convert(const base::Value& value,
292 ScopedVector<NestedType>* field) const override {
[email protected]193f946b2011-12-22 18:31:47293 const base::ListValue* list = NULL;
294 if (!value.GetAsList(&list))
[email protected]261c877e2012-01-05 09:46:42295 return false;
[email protected]193f946b2011-12-22 18:31:47296
297 field->reserve(list->GetSize());
298 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37299 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47300 if (!list->Get(i, &element))
301 continue;
302
dcheng093de9b2016-04-04 21:25:51303 std::unique_ptr<NestedType> nested(new NestedType);
[email protected]50fa6f922012-01-26 19:32:36304 if (converter_.Convert(*element, nested.get())) {
305 field->push_back(nested.release());
[email protected]a9b8e0a2012-01-14 05:36:12306 } else {
[email protected]261c877e2012-01-05 09:46:42307 DVLOG(1) << "failure at " << i << "-th element";
308 return false;
309 }
[email protected]193f946b2011-12-22 18:31:47310 }
[email protected]261c877e2012-01-05 09:46:42311 return true;
[email protected]193f946b2011-12-22 18:31:47312 }
313
314 private:
315 JSONValueConverter<NestedType> converter_;
316 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
317};
318
[email protected]4e1ec032012-05-03 18:31:54319template <typename NestedType>
320class RepeatedCustomValueConverter
321 : public ValueConverter<ScopedVector<NestedType> > {
322 public:
323 typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
324
325 RepeatedCustomValueConverter(ConvertFunc convert_func)
326 : convert_func_(convert_func) {}
327
nickc0b001062015-04-22 23:17:20328 bool Convert(const base::Value& value,
329 ScopedVector<NestedType>* field) const override {
[email protected]4e1ec032012-05-03 18:31:54330 const base::ListValue* list = NULL;
331 if (!value.GetAsList(&list))
332 return false;
333
334 field->reserve(list->GetSize());
335 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37336 const base::Value* element = NULL;
[email protected]4e1ec032012-05-03 18:31:54337 if (!list->Get(i, &element))
338 continue;
339
dcheng093de9b2016-04-04 21:25:51340 std::unique_ptr<NestedType> nested(new NestedType);
[email protected]4e1ec032012-05-03 18:31:54341 if ((*convert_func_)(element, nested.get())) {
342 field->push_back(nested.release());
343 } else {
344 DVLOG(1) << "failure at " << i << "-th element";
345 return false;
346 }
347 }
348 return true;
349 }
350
351 private:
352 ConvertFunc convert_func_;
353 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
354};
355
356
[email protected]193f946b2011-12-22 18:31:47357} // namespace internal
358
359template <class StructType>
360class JSONValueConverter {
361 public:
362 JSONValueConverter() {
363 StructType::RegisterJSONConverter(this);
364 }
365
[email protected]193f946b2011-12-22 18:31:47366 void RegisterIntField(const std::string& field_name,
367 int StructType::* field) {
368 fields_.push_back(new internal::FieldConverter<StructType, int>(
369 field_name, field, new internal::BasicValueConverter<int>));
370 }
371
372 void RegisterStringField(const std::string& field_name,
[email protected]261c877e2012-01-05 09:46:42373 std::string StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47374 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
375 field_name, field, new internal::BasicValueConverter<std::string>));
376 }
377
[email protected]261c877e2012-01-05 09:46:42378 void RegisterStringField(const std::string& field_name,
379 string16 StructType::* field) {
380 fields_.push_back(new internal::FieldConverter<StructType, string16>(
381 field_name, field, new internal::BasicValueConverter<string16>));
382 }
383
[email protected]193f946b2011-12-22 18:31:47384 void RegisterBoolField(const std::string& field_name,
385 bool StructType::* field) {
386 fields_.push_back(new internal::FieldConverter<StructType, bool>(
387 field_name, field, new internal::BasicValueConverter<bool>));
388 }
389
390 void RegisterDoubleField(const std::string& field_name,
391 double StructType::* field) {
392 fields_.push_back(new internal::FieldConverter<StructType, double>(
393 field_name, field, new internal::BasicValueConverter<double>));
394 }
395
396 template <class NestedType>
397 void RegisterNestedField(
398 const std::string& field_name, NestedType StructType::* field) {
399 fields_.push_back(new internal::FieldConverter<StructType, NestedType>(
400 field_name,
401 field,
402 new internal::NestedValueConverter<NestedType>));
403 }
404
[email protected]6009ca92012-01-13 02:18:02405 template <typename FieldType>
406 void RegisterCustomField(
407 const std::string& field_name,
408 FieldType StructType::* field,
409 bool (*convert_func)(const StringPiece&, FieldType*)) {
410 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
411 field_name,
412 field,
413 new internal::CustomFieldConverter<FieldType>(convert_func)));
414 }
415
[email protected]038cf352012-04-13 00:14:15416 template <typename FieldType>
417 void RegisterCustomValueField(
418 const std::string& field_name,
419 FieldType StructType::* field,
420 bool (*convert_func)(const base::Value*, FieldType*)) {
421 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
422 field_name,
423 field,
424 new internal::ValueFieldConverter<FieldType>(convert_func)));
425 }
426
[email protected]193f946b2011-12-22 18:31:47427 void RegisterRepeatedInt(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12428 ScopedVector<int> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47429 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12430 new internal::FieldConverter<StructType, ScopedVector<int> >(
[email protected]193f946b2011-12-22 18:31:47431 field_name, field, new internal::RepeatedValueConverter<int>));
432 }
433
434 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12435 ScopedVector<std::string> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47436 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12437 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
[email protected]193f946b2011-12-22 18:31:47438 field_name,
439 field,
440 new internal::RepeatedValueConverter<std::string>));
441 }
442
[email protected]261c877e2012-01-05 09:46:42443 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12444 ScopedVector<string16> StructType::* field) {
[email protected]261c877e2012-01-05 09:46:42445 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12446 new internal::FieldConverter<StructType, ScopedVector<string16> >(
[email protected]261c877e2012-01-05 09:46:42447 field_name,
448 field,
449 new internal::RepeatedValueConverter<string16>));
450 }
451
[email protected]193f946b2011-12-22 18:31:47452 void RegisterRepeatedDouble(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12453 ScopedVector<double> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47454 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12455 new internal::FieldConverter<StructType, ScopedVector<double> >(
[email protected]193f946b2011-12-22 18:31:47456 field_name, field, new internal::RepeatedValueConverter<double>));
457 }
458
459 void RegisterRepeatedBool(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12460 ScopedVector<bool> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47461 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12462 new internal::FieldConverter<StructType, ScopedVector<bool> >(
[email protected]193f946b2011-12-22 18:31:47463 field_name, field, new internal::RepeatedValueConverter<bool>));
464 }
465
466 template <class NestedType>
[email protected]4e1ec032012-05-03 18:31:54467 void RegisterRepeatedCustomValue(
468 const std::string& field_name,
469 ScopedVector<NestedType> StructType::* field,
470 bool (*convert_func)(const base::Value*, NestedType*)) {
471 fields_.push_back(
472 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
473 field_name,
474 field,
475 new internal::RepeatedCustomValueConverter<NestedType>(
476 convert_func)));
477 }
478
479 template <class NestedType>
[email protected]193f946b2011-12-22 18:31:47480 void RegisterRepeatedMessage(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12481 ScopedVector<NestedType> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47482 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12483 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
[email protected]193f946b2011-12-22 18:31:47484 field_name,
485 field,
486 new internal::RepeatedMessageConverter<NestedType>));
487 }
488
[email protected]261c877e2012-01-05 09:46:42489 bool Convert(const base::Value& value, StructType* output) const {
[email protected]193f946b2011-12-22 18:31:47490 const DictionaryValue* dictionary_value = NULL;
491 if (!value.GetAsDictionary(&dictionary_value))
[email protected]261c877e2012-01-05 09:46:42492 return false;
[email protected]193f946b2011-12-22 18:31:47493
[email protected]a9b8e0a2012-01-14 05:36:12494 for(size_t i = 0; i < fields_.size(); ++i) {
[email protected]983b9b72012-01-27 07:12:21495 const internal::FieldConverterBase<StructType>* field_converter =
496 fields_[i];
[email protected]a61890e2012-07-27 22:27:11497 const base::Value* field = NULL;
[email protected]a9b8e0a2012-01-14 05:36:12498 if (dictionary_value->Get(field_converter->field_path(), &field)) {
499 if (!field_converter->ConvertField(*field, output)) {
500 DVLOG(1) << "failure at field " << field_converter->field_path();
[email protected]261c877e2012-01-05 09:46:42501 return false;
502 }
[email protected]193f946b2011-12-22 18:31:47503 }
504 }
[email protected]261c877e2012-01-05 09:46:42505 return true;
[email protected]193f946b2011-12-22 18:31:47506 }
507
508 private:
[email protected]983b9b72012-01-27 07:12:21509 ScopedVector<internal::FieldConverterBase<StructType> > fields_;
[email protected]193f946b2011-12-22 18:31:47510
511 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
512};
513
514} // namespace base
515
516#endif // BASE_JSON_JSON_VALUE_CONVERTER_H_