blob: f94d46e3ccf71cbd7a19aeef0c608dcd17b14a06 [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
8#include <string>
9#include <vector>
10
dmichael7d09007e2014-12-18 22:30:1111#include "base/base_export.h"
[email protected]193f946b2011-12-22 18:31:4712#include "base/basictypes.h"
13#include "base/logging.h"
14#include "base/memory/scoped_ptr.h"
[email protected]a9b8e0a2012-01-14 05:36:1215#include "base/memory/scoped_vector.h"
[email protected]193f946b2011-12-22 18:31:4716#include "base/stl_util.h"
[email protected]d529cb02013-06-10 19:06:5717#include "base/strings/string16.h"
[email protected]eb62f7262013-03-30 14:29:0018#include "base/strings/string_piece.h"
[email protected]193f946b2011-12-22 18:31:4719#include "base/values.h"
20
21// JSONValueConverter converts a JSON value into a C++ struct in a
22// lightweight way.
23//
24// Usage:
25// For real examples, you may want to refer to _unittest.cc file.
26//
27// Assume that you have a struct like this:
28// struct Message {
29// int foo;
30// std::string bar;
31// static void RegisterJSONConverter(
32// JSONValueConverter<Message>* converter);
33// };
34//
35// And you want to parse a json data into this struct. First, you
36// need to declare RegisterJSONConverter() method in your struct.
37// // static
38// void Message::RegisterJSONConverter(
39// JSONValueConverter<Message>* converter) {
40// converter->RegisterIntField("foo", &Message::foo);
41// converter->RegisterStringField("bar", &Message::bar);
42// }
43//
44// Then, you just instantiate your JSONValueConverter of your type and call
45// Convert() method.
46// Message message;
47// JSONValueConverter<Message> converter;
48// converter.Convert(json, &message);
49//
[email protected]261c877e2012-01-05 09:46:4250// Convert() returns false when it fails. Here "fail" means that the value is
51// structurally different from expected, such like a string value appears
52// for an int field. Do not report failures for missing fields.
53// Also note that Convert() will modify the passed |message| even when it
54// fails for performance reason.
55//
[email protected]193f946b2011-12-22 18:31:4756// For nested field, the internal message also has to implement the registration
57// method. Then, just use RegisterNestedField() from the containing struct's
58// RegisterJSONConverter method.
59// struct Nested {
60// Message foo;
[email protected]261c877e2012-01-05 09:46:4261// static void RegisterJSONConverter(...) {
[email protected]193f946b2011-12-22 18:31:4762// ...
63// converter->RegisterNestedField("foo", &Nested::foo);
64// }
65// };
66//
[email protected]a9b8e0a2012-01-14 05:36:1267// For repeated field, we just assume ScopedVector for its container
[email protected]193f946b2011-12-22 18:31:4768// and you can put RegisterRepeatedInt or some other types. Use
69// RegisterRepeatedMessage for nested repeated fields.
70//
[email protected]6009ca92012-01-13 02:18:0271// Sometimes JSON format uses string representations for other types such
72// like enum, timestamp, or URL. You can use RegisterCustomField method
73// and specify a function to convert a StringPiece to your type.
74// bool ConvertFunc(const StringPiece& s, YourEnum* result) {
75// // do something and return true if succeed...
76// }
77// struct Message {
78// YourEnum ye;
79// ...
80// static void RegisterJSONConverter(...) {
81// ...
82// converter->RegsiterCustomField<YourEnum>(
83// "your_enum", &Message::ye, &ConvertFunc);
84// }
85// };
[email protected]193f946b2011-12-22 18:31:4786
87namespace base {
88
89template <typename StructType>
90class JSONValueConverter;
91
92namespace internal {
93
[email protected]983b9b72012-01-27 07:12:2194template<typename StructType>
[email protected]193f946b2011-12-22 18:31:4795class FieldConverterBase {
96 public:
[email protected]983b9b72012-01-27 07:12:2197 explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
98 virtual ~FieldConverterBase() {}
99 virtual bool ConvertField(const base::Value& value, StructType* obj)
100 const = 0;
[email protected]193f946b2011-12-22 18:31:47101 const std::string& field_path() const { return field_path_; }
102
103 private:
104 std::string field_path_;
105 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
106};
107
108template <typename FieldType>
109class ValueConverter {
110 public:
111 virtual ~ValueConverter() {}
[email protected]261c877e2012-01-05 09:46:42112 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
[email protected]193f946b2011-12-22 18:31:47113};
114
115template <typename StructType, typename FieldType>
[email protected]983b9b72012-01-27 07:12:21116class FieldConverter : public FieldConverterBase<StructType> {
[email protected]193f946b2011-12-22 18:31:47117 public:
118 explicit FieldConverter(const std::string& path,
119 FieldType StructType::* field,
120 ValueConverter<FieldType>* converter)
[email protected]983b9b72012-01-27 07:12:21121 : FieldConverterBase<StructType>(path),
[email protected]193f946b2011-12-22 18:31:47122 field_pointer_(field),
123 value_converter_(converter) {
124 }
125
nickc0b001062015-04-22 23:17:20126 bool ConvertField(const base::Value& value, StructType* dst) const override {
[email protected]261c877e2012-01-05 09:46:42127 return value_converter_->Convert(value, &(dst->*field_pointer_));
[email protected]193f946b2011-12-22 18:31:47128 }
129
130 private:
131 FieldType StructType::* field_pointer_;
132 scoped_ptr<ValueConverter<FieldType> > value_converter_;
133 DISALLOW_COPY_AND_ASSIGN(FieldConverter);
134};
135
136template <typename FieldType>
137class BasicValueConverter;
138
139template <>
dmichael7d09007e2014-12-18 22:30:11140class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
[email protected]193f946b2011-12-22 18:31:47141 public:
142 BasicValueConverter() {}
143
dmichael7d09007e2014-12-18 22:30:11144 bool Convert(const base::Value& value, int* field) const override;
[email protected]193f946b2011-12-22 18:31:47145
146 private:
147 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
148};
149
150template <>
dmichael7d09007e2014-12-18 22:30:11151class BASE_EXPORT BasicValueConverter<std::string>
152 : public ValueConverter<std::string> {
[email protected]193f946b2011-12-22 18:31:47153 public:
154 BasicValueConverter() {}
155
dmichael7d09007e2014-12-18 22:30:11156 bool Convert(const base::Value& value, std::string* field) const override;
[email protected]261c877e2012-01-05 09:46:42157
158 private:
159 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
160};
161
162template <>
dmichael7d09007e2014-12-18 22:30:11163class BASE_EXPORT BasicValueConverter<string16>
164 : public ValueConverter<string16> {
[email protected]261c877e2012-01-05 09:46:42165 public:
166 BasicValueConverter() {}
167
dmichael7d09007e2014-12-18 22:30:11168 bool Convert(const base::Value& value, string16* field) const override;
[email protected]193f946b2011-12-22 18:31:47169
170 private:
171 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
172};
173
174template <>
dmichael7d09007e2014-12-18 22:30:11175class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
[email protected]193f946b2011-12-22 18:31:47176 public:
177 BasicValueConverter() {}
178
dmichael7d09007e2014-12-18 22:30:11179 bool Convert(const base::Value& value, double* field) const override;
[email protected]193f946b2011-12-22 18:31:47180
181 private:
182 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
183};
184
185template <>
dmichael7d09007e2014-12-18 22:30:11186class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
[email protected]193f946b2011-12-22 18:31:47187 public:
188 BasicValueConverter() {}
189
dmichael7d09007e2014-12-18 22:30:11190 bool Convert(const base::Value& value, bool* field) const override;
[email protected]193f946b2011-12-22 18:31:47191
192 private:
193 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
194};
195
[email protected]6009ca92012-01-13 02:18:02196template <typename FieldType>
[email protected]038cf352012-04-13 00:14:15197class ValueFieldConverter : public ValueConverter<FieldType> {
198 public:
199 typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
200
201 ValueFieldConverter(ConvertFunc convert_func)
202 : convert_func_(convert_func) {}
203
nickc0b001062015-04-22 23:17:20204 bool Convert(const base::Value& value, FieldType* field) const override {
[email protected]038cf352012-04-13 00:14:15205 return convert_func_(&value, field);
206 }
207
208 private:
209 ConvertFunc convert_func_;
210
211 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
212};
213
214template <typename FieldType>
[email protected]6009ca92012-01-13 02:18:02215class CustomFieldConverter : public ValueConverter<FieldType> {
216 public:
217 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
218
219 CustomFieldConverter(ConvertFunc convert_func)
220 : convert_func_(convert_func) {}
221
nickc0b001062015-04-22 23:17:20222 bool Convert(const base::Value& value, FieldType* field) const override {
[email protected]6009ca92012-01-13 02:18:02223 std::string string_value;
224 return value.GetAsString(&string_value) &&
225 convert_func_(string_value, field);
226 }
227
228 private:
229 ConvertFunc convert_func_;
230
231 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
232};
233
[email protected]193f946b2011-12-22 18:31:47234template <typename NestedType>
235class NestedValueConverter : public ValueConverter<NestedType> {
236 public:
237 NestedValueConverter() {}
238
nickc0b001062015-04-22 23:17:20239 bool Convert(const base::Value& value, NestedType* field) const override {
[email protected]261c877e2012-01-05 09:46:42240 return converter_.Convert(value, field);
[email protected]193f946b2011-12-22 18:31:47241 }
242
243 private:
244 JSONValueConverter<NestedType> converter_;
245 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
246};
247
248template <typename Element>
[email protected]a9b8e0a2012-01-14 05:36:12249class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
[email protected]193f946b2011-12-22 18:31:47250 public:
251 RepeatedValueConverter() {}
252
nickc0b001062015-04-22 23:17:20253 bool Convert(const base::Value& value,
254 ScopedVector<Element>* field) const override {
[email protected]193f946b2011-12-22 18:31:47255 const base::ListValue* list = NULL;
256 if (!value.GetAsList(&list)) {
257 // The field is not a list.
[email protected]261c877e2012-01-05 09:46:42258 return false;
[email protected]193f946b2011-12-22 18:31:47259 }
260
261 field->reserve(list->GetSize());
262 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37263 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47264 if (!list->Get(i, &element))
265 continue;
266
[email protected]50fa6f922012-01-26 19:32:36267 scoped_ptr<Element> e(new Element);
268 if (basic_converter_.Convert(*element, e.get())) {
269 field->push_back(e.release());
[email protected]a9b8e0a2012-01-14 05:36:12270 } else {
[email protected]261c877e2012-01-05 09:46:42271 DVLOG(1) << "failure at " << i << "-th element";
272 return false;
273 }
[email protected]193f946b2011-12-22 18:31:47274 }
[email protected]261c877e2012-01-05 09:46:42275 return true;
[email protected]193f946b2011-12-22 18:31:47276 }
277
278 private:
279 BasicValueConverter<Element> basic_converter_;
280 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
281};
282
283template <typename NestedType>
284class RepeatedMessageConverter
[email protected]a9b8e0a2012-01-14 05:36:12285 : public ValueConverter<ScopedVector<NestedType> > {
[email protected]193f946b2011-12-22 18:31:47286 public:
287 RepeatedMessageConverter() {}
288
nickc0b001062015-04-22 23:17:20289 bool Convert(const base::Value& value,
290 ScopedVector<NestedType>* field) const override {
[email protected]193f946b2011-12-22 18:31:47291 const base::ListValue* list = NULL;
292 if (!value.GetAsList(&list))
[email protected]261c877e2012-01-05 09:46:42293 return false;
[email protected]193f946b2011-12-22 18:31:47294
295 field->reserve(list->GetSize());
296 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37297 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47298 if (!list->Get(i, &element))
299 continue;
300
[email protected]50fa6f922012-01-26 19:32:36301 scoped_ptr<NestedType> nested(new NestedType);
302 if (converter_.Convert(*element, nested.get())) {
303 field->push_back(nested.release());
[email protected]a9b8e0a2012-01-14 05:36:12304 } else {
[email protected]261c877e2012-01-05 09:46:42305 DVLOG(1) << "failure at " << i << "-th element";
306 return false;
307 }
[email protected]193f946b2011-12-22 18:31:47308 }
[email protected]261c877e2012-01-05 09:46:42309 return true;
[email protected]193f946b2011-12-22 18:31:47310 }
311
312 private:
313 JSONValueConverter<NestedType> converter_;
314 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
315};
316
[email protected]4e1ec032012-05-03 18:31:54317template <typename NestedType>
318class RepeatedCustomValueConverter
319 : public ValueConverter<ScopedVector<NestedType> > {
320 public:
321 typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
322
323 RepeatedCustomValueConverter(ConvertFunc convert_func)
324 : convert_func_(convert_func) {}
325
nickc0b001062015-04-22 23:17:20326 bool Convert(const base::Value& value,
327 ScopedVector<NestedType>* field) const override {
[email protected]4e1ec032012-05-03 18:31:54328 const base::ListValue* list = NULL;
329 if (!value.GetAsList(&list))
330 return false;
331
332 field->reserve(list->GetSize());
333 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37334 const base::Value* element = NULL;
[email protected]4e1ec032012-05-03 18:31:54335 if (!list->Get(i, &element))
336 continue;
337
338 scoped_ptr<NestedType> nested(new NestedType);
339 if ((*convert_func_)(element, nested.get())) {
340 field->push_back(nested.release());
341 } else {
342 DVLOG(1) << "failure at " << i << "-th element";
343 return false;
344 }
345 }
346 return true;
347 }
348
349 private:
350 ConvertFunc convert_func_;
351 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
352};
353
354
[email protected]193f946b2011-12-22 18:31:47355} // namespace internal
356
357template <class StructType>
358class JSONValueConverter {
359 public:
360 JSONValueConverter() {
361 StructType::RegisterJSONConverter(this);
362 }
363
[email protected]193f946b2011-12-22 18:31:47364 void RegisterIntField(const std::string& field_name,
365 int StructType::* field) {
366 fields_.push_back(new internal::FieldConverter<StructType, int>(
367 field_name, field, new internal::BasicValueConverter<int>));
368 }
369
370 void RegisterStringField(const std::string& field_name,
[email protected]261c877e2012-01-05 09:46:42371 std::string StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47372 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
373 field_name, field, new internal::BasicValueConverter<std::string>));
374 }
375
[email protected]261c877e2012-01-05 09:46:42376 void RegisterStringField(const std::string& field_name,
377 string16 StructType::* field) {
378 fields_.push_back(new internal::FieldConverter<StructType, string16>(
379 field_name, field, new internal::BasicValueConverter<string16>));
380 }
381
[email protected]193f946b2011-12-22 18:31:47382 void RegisterBoolField(const std::string& field_name,
383 bool StructType::* field) {
384 fields_.push_back(new internal::FieldConverter<StructType, bool>(
385 field_name, field, new internal::BasicValueConverter<bool>));
386 }
387
388 void RegisterDoubleField(const std::string& field_name,
389 double StructType::* field) {
390 fields_.push_back(new internal::FieldConverter<StructType, double>(
391 field_name, field, new internal::BasicValueConverter<double>));
392 }
393
394 template <class NestedType>
395 void RegisterNestedField(
396 const std::string& field_name, NestedType StructType::* field) {
397 fields_.push_back(new internal::FieldConverter<StructType, NestedType>(
398 field_name,
399 field,
400 new internal::NestedValueConverter<NestedType>));
401 }
402
[email protected]6009ca92012-01-13 02:18:02403 template <typename FieldType>
404 void RegisterCustomField(
405 const std::string& field_name,
406 FieldType StructType::* field,
407 bool (*convert_func)(const StringPiece&, FieldType*)) {
408 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
409 field_name,
410 field,
411 new internal::CustomFieldConverter<FieldType>(convert_func)));
412 }
413
[email protected]038cf352012-04-13 00:14:15414 template <typename FieldType>
415 void RegisterCustomValueField(
416 const std::string& field_name,
417 FieldType StructType::* field,
418 bool (*convert_func)(const base::Value*, FieldType*)) {
419 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
420 field_name,
421 field,
422 new internal::ValueFieldConverter<FieldType>(convert_func)));
423 }
424
[email protected]193f946b2011-12-22 18:31:47425 void RegisterRepeatedInt(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12426 ScopedVector<int> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47427 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12428 new internal::FieldConverter<StructType, ScopedVector<int> >(
[email protected]193f946b2011-12-22 18:31:47429 field_name, field, new internal::RepeatedValueConverter<int>));
430 }
431
432 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12433 ScopedVector<std::string> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47434 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12435 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
[email protected]193f946b2011-12-22 18:31:47436 field_name,
437 field,
438 new internal::RepeatedValueConverter<std::string>));
439 }
440
[email protected]261c877e2012-01-05 09:46:42441 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12442 ScopedVector<string16> StructType::* field) {
[email protected]261c877e2012-01-05 09:46:42443 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12444 new internal::FieldConverter<StructType, ScopedVector<string16> >(
[email protected]261c877e2012-01-05 09:46:42445 field_name,
446 field,
447 new internal::RepeatedValueConverter<string16>));
448 }
449
[email protected]193f946b2011-12-22 18:31:47450 void RegisterRepeatedDouble(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12451 ScopedVector<double> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47452 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12453 new internal::FieldConverter<StructType, ScopedVector<double> >(
[email protected]193f946b2011-12-22 18:31:47454 field_name, field, new internal::RepeatedValueConverter<double>));
455 }
456
457 void RegisterRepeatedBool(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12458 ScopedVector<bool> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47459 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12460 new internal::FieldConverter<StructType, ScopedVector<bool> >(
[email protected]193f946b2011-12-22 18:31:47461 field_name, field, new internal::RepeatedValueConverter<bool>));
462 }
463
464 template <class NestedType>
[email protected]4e1ec032012-05-03 18:31:54465 void RegisterRepeatedCustomValue(
466 const std::string& field_name,
467 ScopedVector<NestedType> StructType::* field,
468 bool (*convert_func)(const base::Value*, NestedType*)) {
469 fields_.push_back(
470 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
471 field_name,
472 field,
473 new internal::RepeatedCustomValueConverter<NestedType>(
474 convert_func)));
475 }
476
477 template <class NestedType>
[email protected]193f946b2011-12-22 18:31:47478 void RegisterRepeatedMessage(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12479 ScopedVector<NestedType> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47480 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12481 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
[email protected]193f946b2011-12-22 18:31:47482 field_name,
483 field,
484 new internal::RepeatedMessageConverter<NestedType>));
485 }
486
[email protected]261c877e2012-01-05 09:46:42487 bool Convert(const base::Value& value, StructType* output) const {
[email protected]193f946b2011-12-22 18:31:47488 const DictionaryValue* dictionary_value = NULL;
489 if (!value.GetAsDictionary(&dictionary_value))
[email protected]261c877e2012-01-05 09:46:42490 return false;
[email protected]193f946b2011-12-22 18:31:47491
[email protected]a9b8e0a2012-01-14 05:36:12492 for(size_t i = 0; i < fields_.size(); ++i) {
[email protected]983b9b72012-01-27 07:12:21493 const internal::FieldConverterBase<StructType>* field_converter =
494 fields_[i];
[email protected]a61890e2012-07-27 22:27:11495 const base::Value* field = NULL;
[email protected]a9b8e0a2012-01-14 05:36:12496 if (dictionary_value->Get(field_converter->field_path(), &field)) {
497 if (!field_converter->ConvertField(*field, output)) {
498 DVLOG(1) << "failure at field " << field_converter->field_path();
[email protected]261c877e2012-01-05 09:46:42499 return false;
500 }
[email protected]193f946b2011-12-22 18:31:47501 }
502 }
[email protected]261c877e2012-01-05 09:46:42503 return true;
[email protected]193f946b2011-12-22 18:31:47504 }
505
506 private:
[email protected]983b9b72012-01-27 07:12:21507 ScopedVector<internal::FieldConverterBase<StructType> > fields_;
[email protected]193f946b2011-12-22 18:31:47508
509 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
510};
511
512} // namespace base
513
514#endif // BASE_JSON_JSON_VALUE_CONVERTER_H_