blob: 59778e5c8b98df7b6510391989c3f2b0464ac138 [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
[email protected]193f946b2011-12-22 18:31:4711#include "base/basictypes.h"
12#include "base/logging.h"
13#include "base/memory/scoped_ptr.h"
[email protected]a9b8e0a2012-01-14 05:36:1214#include "base/memory/scoped_vector.h"
[email protected]193f946b2011-12-22 18:31:4715#include "base/stl_util.h"
[email protected]261c877e2012-01-05 09:46:4216#include "base/string16.h"
[email protected]eb62f7262013-03-30 14:29:0017#include "base/strings/string_piece.h"
[email protected]193f946b2011-12-22 18:31:4718#include "base/values.h"
19
20// JSONValueConverter converts a JSON value into a C++ struct in a
21// lightweight way.
22//
23// Usage:
24// For real examples, you may want to refer to _unittest.cc file.
25//
26// Assume that you have a struct like this:
27// struct Message {
28// int foo;
29// std::string bar;
30// static void RegisterJSONConverter(
31// JSONValueConverter<Message>* converter);
32// };
33//
34// And you want to parse a json data into this struct. First, you
35// need to declare RegisterJSONConverter() method in your struct.
36// // static
37// void Message::RegisterJSONConverter(
38// JSONValueConverter<Message>* converter) {
39// converter->RegisterIntField("foo", &Message::foo);
40// converter->RegisterStringField("bar", &Message::bar);
41// }
42//
43// Then, you just instantiate your JSONValueConverter of your type and call
44// Convert() method.
45// Message message;
46// JSONValueConverter<Message> converter;
47// converter.Convert(json, &message);
48//
[email protected]261c877e2012-01-05 09:46:4249// Convert() returns false when it fails. Here "fail" means that the value is
50// structurally different from expected, such like a string value appears
51// for an int field. Do not report failures for missing fields.
52// Also note that Convert() will modify the passed |message| even when it
53// fails for performance reason.
54//
[email protected]193f946b2011-12-22 18:31:4755// For nested field, the internal message also has to implement the registration
56// method. Then, just use RegisterNestedField() from the containing struct's
57// RegisterJSONConverter method.
58// struct Nested {
59// Message foo;
[email protected]261c877e2012-01-05 09:46:4260// static void RegisterJSONConverter(...) {
[email protected]193f946b2011-12-22 18:31:4761// ...
62// converter->RegisterNestedField("foo", &Nested::foo);
63// }
64// };
65//
[email protected]a9b8e0a2012-01-14 05:36:1266// For repeated field, we just assume ScopedVector for its container
[email protected]193f946b2011-12-22 18:31:4767// and you can put RegisterRepeatedInt or some other types. Use
68// RegisterRepeatedMessage for nested repeated fields.
69//
[email protected]6009ca92012-01-13 02:18:0270// Sometimes JSON format uses string representations for other types such
71// like enum, timestamp, or URL. You can use RegisterCustomField method
72// and specify a function to convert a StringPiece to your type.
73// bool ConvertFunc(const StringPiece& s, YourEnum* result) {
74// // do something and return true if succeed...
75// }
76// struct Message {
77// YourEnum ye;
78// ...
79// static void RegisterJSONConverter(...) {
80// ...
81// converter->RegsiterCustomField<YourEnum>(
82// "your_enum", &Message::ye, &ConvertFunc);
83// }
84// };
[email protected]193f946b2011-12-22 18:31:4785
86namespace base {
87
88template <typename StructType>
89class JSONValueConverter;
90
91namespace internal {
92
[email protected]983b9b72012-01-27 07:12:2193template<typename StructType>
[email protected]193f946b2011-12-22 18:31:4794class FieldConverterBase {
95 public:
[email protected]983b9b72012-01-27 07:12:2196 explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
97 virtual ~FieldConverterBase() {}
98 virtual bool ConvertField(const base::Value& value, StructType* obj)
99 const = 0;
[email protected]193f946b2011-12-22 18:31:47100 const std::string& field_path() const { return field_path_; }
101
102 private:
103 std::string field_path_;
104 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
105};
106
107template <typename FieldType>
108class ValueConverter {
109 public:
110 virtual ~ValueConverter() {}
[email protected]261c877e2012-01-05 09:46:42111 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
[email protected]193f946b2011-12-22 18:31:47112};
113
114template <typename StructType, typename FieldType>
[email protected]983b9b72012-01-27 07:12:21115class FieldConverter : public FieldConverterBase<StructType> {
[email protected]193f946b2011-12-22 18:31:47116 public:
117 explicit FieldConverter(const std::string& path,
118 FieldType StructType::* field,
119 ValueConverter<FieldType>* converter)
[email protected]983b9b72012-01-27 07:12:21120 : FieldConverterBase<StructType>(path),
[email protected]193f946b2011-12-22 18:31:47121 field_pointer_(field),
122 value_converter_(converter) {
123 }
124
[email protected]261c877e2012-01-05 09:46:42125 virtual bool ConvertField(
[email protected]983b9b72012-01-27 07:12:21126 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 <>
140class BasicValueConverter<int> : public ValueConverter<int> {
141 public:
142 BasicValueConverter() {}
143
[email protected]261c877e2012-01-05 09:46:42144 virtual bool Convert(const base::Value& value, int* field) const OVERRIDE {
145 return value.GetAsInteger(field);
[email protected]193f946b2011-12-22 18:31:47146 }
147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
150};
151
152template <>
153class BasicValueConverter<std::string> : public ValueConverter<std::string> {
154 public:
155 BasicValueConverter() {}
156
[email protected]261c877e2012-01-05 09:46:42157 virtual bool Convert(
[email protected]193f946b2011-12-22 18:31:47158 const base::Value& value, std::string* field) const OVERRIDE {
[email protected]261c877e2012-01-05 09:46:42159 return value.GetAsString(field);
160 }
161
162 private:
163 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
164};
165
166template <>
167class BasicValueConverter<string16> : public ValueConverter<string16> {
168 public:
169 BasicValueConverter() {}
170
171 virtual bool Convert(
172 const base::Value& value, string16* field) const OVERRIDE {
173 return value.GetAsString(field);
[email protected]193f946b2011-12-22 18:31:47174 }
175
176 private:
177 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
178};
179
180template <>
181class BasicValueConverter<double> : public ValueConverter<double> {
182 public:
183 BasicValueConverter() {}
184
[email protected]261c877e2012-01-05 09:46:42185 virtual bool Convert(const base::Value& value, double* field) const OVERRIDE {
186 return value.GetAsDouble(field);
[email protected]193f946b2011-12-22 18:31:47187 }
188
189 private:
190 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
191};
192
193template <>
194class BasicValueConverter<bool> : public ValueConverter<bool> {
195 public:
196 BasicValueConverter() {}
197
[email protected]261c877e2012-01-05 09:46:42198 virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE {
199 return value.GetAsBoolean(field);
[email protected]193f946b2011-12-22 18:31:47200 }
201
202 private:
203 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
204};
205
[email protected]6009ca92012-01-13 02:18:02206template <typename FieldType>
[email protected]038cf352012-04-13 00:14:15207class ValueFieldConverter : public ValueConverter<FieldType> {
208 public:
209 typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
210
211 ValueFieldConverter(ConvertFunc convert_func)
212 : convert_func_(convert_func) {}
213
214 virtual bool Convert(const base::Value& value,
215 FieldType* field) const OVERRIDE {
216 return convert_func_(&value, field);
217 }
218
219 private:
220 ConvertFunc convert_func_;
221
222 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
223};
224
225template <typename FieldType>
[email protected]6009ca92012-01-13 02:18:02226class CustomFieldConverter : public ValueConverter<FieldType> {
227 public:
228 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
229
230 CustomFieldConverter(ConvertFunc convert_func)
231 : convert_func_(convert_func) {}
232
233 virtual bool Convert(const base::Value& value,
234 FieldType* field) const OVERRIDE {
235 std::string string_value;
236 return value.GetAsString(&string_value) &&
237 convert_func_(string_value, field);
238 }
239
240 private:
241 ConvertFunc convert_func_;
242
243 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
244};
245
[email protected]193f946b2011-12-22 18:31:47246template <typename NestedType>
247class NestedValueConverter : public ValueConverter<NestedType> {
248 public:
249 NestedValueConverter() {}
250
[email protected]261c877e2012-01-05 09:46:42251 virtual bool Convert(
[email protected]193f946b2011-12-22 18:31:47252 const base::Value& value, NestedType* field) const OVERRIDE {
[email protected]261c877e2012-01-05 09:46:42253 return converter_.Convert(value, field);
[email protected]193f946b2011-12-22 18:31:47254 }
255
256 private:
257 JSONValueConverter<NestedType> converter_;
258 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
259};
260
261template <typename Element>
[email protected]a9b8e0a2012-01-14 05:36:12262class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
[email protected]193f946b2011-12-22 18:31:47263 public:
264 RepeatedValueConverter() {}
265
[email protected]261c877e2012-01-05 09:46:42266 virtual bool Convert(
[email protected]a9b8e0a2012-01-14 05:36:12267 const base::Value& value, ScopedVector<Element>* field) const OVERRIDE {
[email protected]193f946b2011-12-22 18:31:47268 const base::ListValue* list = NULL;
269 if (!value.GetAsList(&list)) {
270 // The field is not a list.
[email protected]261c877e2012-01-05 09:46:42271 return false;
[email protected]193f946b2011-12-22 18:31:47272 }
273
274 field->reserve(list->GetSize());
275 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37276 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47277 if (!list->Get(i, &element))
278 continue;
279
[email protected]50fa6f922012-01-26 19:32:36280 scoped_ptr<Element> e(new Element);
281 if (basic_converter_.Convert(*element, e.get())) {
282 field->push_back(e.release());
[email protected]a9b8e0a2012-01-14 05:36:12283 } else {
[email protected]261c877e2012-01-05 09:46:42284 DVLOG(1) << "failure at " << i << "-th element";
285 return false;
286 }
[email protected]193f946b2011-12-22 18:31:47287 }
[email protected]261c877e2012-01-05 09:46:42288 return true;
[email protected]193f946b2011-12-22 18:31:47289 }
290
291 private:
292 BasicValueConverter<Element> basic_converter_;
293 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
294};
295
296template <typename NestedType>
297class RepeatedMessageConverter
[email protected]a9b8e0a2012-01-14 05:36:12298 : public ValueConverter<ScopedVector<NestedType> > {
[email protected]193f946b2011-12-22 18:31:47299 public:
300 RepeatedMessageConverter() {}
301
[email protected]a9b8e0a2012-01-14 05:36:12302 virtual bool Convert(const base::Value& value,
303 ScopedVector<NestedType>* field) const OVERRIDE {
[email protected]193f946b2011-12-22 18:31:47304 const base::ListValue* list = NULL;
305 if (!value.GetAsList(&list))
[email protected]261c877e2012-01-05 09:46:42306 return false;
[email protected]193f946b2011-12-22 18:31:47307
308 field->reserve(list->GetSize());
309 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37310 const base::Value* element = NULL;
[email protected]193f946b2011-12-22 18:31:47311 if (!list->Get(i, &element))
312 continue;
313
[email protected]50fa6f922012-01-26 19:32:36314 scoped_ptr<NestedType> nested(new NestedType);
315 if (converter_.Convert(*element, nested.get())) {
316 field->push_back(nested.release());
[email protected]a9b8e0a2012-01-14 05:36:12317 } else {
[email protected]261c877e2012-01-05 09:46:42318 DVLOG(1) << "failure at " << i << "-th element";
319 return false;
320 }
[email protected]193f946b2011-12-22 18:31:47321 }
[email protected]261c877e2012-01-05 09:46:42322 return true;
[email protected]193f946b2011-12-22 18:31:47323 }
324
325 private:
326 JSONValueConverter<NestedType> converter_;
327 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
328};
329
[email protected]4e1ec032012-05-03 18:31:54330template <typename NestedType>
331class RepeatedCustomValueConverter
332 : public ValueConverter<ScopedVector<NestedType> > {
333 public:
334 typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
335
336 RepeatedCustomValueConverter(ConvertFunc convert_func)
337 : convert_func_(convert_func) {}
338
339 virtual bool Convert(const base::Value& value,
340 ScopedVector<NestedType>* field) const OVERRIDE {
341 const base::ListValue* list = NULL;
342 if (!value.GetAsList(&list))
343 return false;
344
345 field->reserve(list->GetSize());
346 for (size_t i = 0; i < list->GetSize(); ++i) {
[email protected]5d30f92bf2012-08-03 08:43:37347 const base::Value* element = NULL;
[email protected]4e1ec032012-05-03 18:31:54348 if (!list->Get(i, &element))
349 continue;
350
351 scoped_ptr<NestedType> nested(new NestedType);
352 if ((*convert_func_)(element, nested.get())) {
353 field->push_back(nested.release());
354 } else {
355 DVLOG(1) << "failure at " << i << "-th element";
356 return false;
357 }
358 }
359 return true;
360 }
361
362 private:
363 ConvertFunc convert_func_;
364 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
365};
366
367
[email protected]193f946b2011-12-22 18:31:47368} // namespace internal
369
370template <class StructType>
371class JSONValueConverter {
372 public:
373 JSONValueConverter() {
374 StructType::RegisterJSONConverter(this);
375 }
376
[email protected]193f946b2011-12-22 18:31:47377 void RegisterIntField(const std::string& field_name,
378 int StructType::* field) {
379 fields_.push_back(new internal::FieldConverter<StructType, int>(
380 field_name, field, new internal::BasicValueConverter<int>));
381 }
382
383 void RegisterStringField(const std::string& field_name,
[email protected]261c877e2012-01-05 09:46:42384 std::string StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47385 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
386 field_name, field, new internal::BasicValueConverter<std::string>));
387 }
388
[email protected]261c877e2012-01-05 09:46:42389 void RegisterStringField(const std::string& field_name,
390 string16 StructType::* field) {
391 fields_.push_back(new internal::FieldConverter<StructType, string16>(
392 field_name, field, new internal::BasicValueConverter<string16>));
393 }
394
[email protected]193f946b2011-12-22 18:31:47395 void RegisterBoolField(const std::string& field_name,
396 bool StructType::* field) {
397 fields_.push_back(new internal::FieldConverter<StructType, bool>(
398 field_name, field, new internal::BasicValueConverter<bool>));
399 }
400
401 void RegisterDoubleField(const std::string& field_name,
402 double StructType::* field) {
403 fields_.push_back(new internal::FieldConverter<StructType, double>(
404 field_name, field, new internal::BasicValueConverter<double>));
405 }
406
407 template <class NestedType>
408 void RegisterNestedField(
409 const std::string& field_name, NestedType StructType::* field) {
410 fields_.push_back(new internal::FieldConverter<StructType, NestedType>(
411 field_name,
412 field,
413 new internal::NestedValueConverter<NestedType>));
414 }
415
[email protected]6009ca92012-01-13 02:18:02416 template <typename FieldType>
417 void RegisterCustomField(
418 const std::string& field_name,
419 FieldType StructType::* field,
420 bool (*convert_func)(const StringPiece&, FieldType*)) {
421 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
422 field_name,
423 field,
424 new internal::CustomFieldConverter<FieldType>(convert_func)));
425 }
426
[email protected]038cf352012-04-13 00:14:15427 template <typename FieldType>
428 void RegisterCustomValueField(
429 const std::string& field_name,
430 FieldType StructType::* field,
431 bool (*convert_func)(const base::Value*, FieldType*)) {
432 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
433 field_name,
434 field,
435 new internal::ValueFieldConverter<FieldType>(convert_func)));
436 }
437
[email protected]193f946b2011-12-22 18:31:47438 void RegisterRepeatedInt(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12439 ScopedVector<int> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47440 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12441 new internal::FieldConverter<StructType, ScopedVector<int> >(
[email protected]193f946b2011-12-22 18:31:47442 field_name, field, new internal::RepeatedValueConverter<int>));
443 }
444
445 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12446 ScopedVector<std::string> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47447 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12448 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
[email protected]193f946b2011-12-22 18:31:47449 field_name,
450 field,
451 new internal::RepeatedValueConverter<std::string>));
452 }
453
[email protected]261c877e2012-01-05 09:46:42454 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12455 ScopedVector<string16> StructType::* field) {
[email protected]261c877e2012-01-05 09:46:42456 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12457 new internal::FieldConverter<StructType, ScopedVector<string16> >(
[email protected]261c877e2012-01-05 09:46:42458 field_name,
459 field,
460 new internal::RepeatedValueConverter<string16>));
461 }
462
[email protected]193f946b2011-12-22 18:31:47463 void RegisterRepeatedDouble(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12464 ScopedVector<double> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47465 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12466 new internal::FieldConverter<StructType, ScopedVector<double> >(
[email protected]193f946b2011-12-22 18:31:47467 field_name, field, new internal::RepeatedValueConverter<double>));
468 }
469
470 void RegisterRepeatedBool(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12471 ScopedVector<bool> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47472 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12473 new internal::FieldConverter<StructType, ScopedVector<bool> >(
[email protected]193f946b2011-12-22 18:31:47474 field_name, field, new internal::RepeatedValueConverter<bool>));
475 }
476
477 template <class NestedType>
[email protected]4e1ec032012-05-03 18:31:54478 void RegisterRepeatedCustomValue(
479 const std::string& field_name,
480 ScopedVector<NestedType> StructType::* field,
481 bool (*convert_func)(const base::Value*, NestedType*)) {
482 fields_.push_back(
483 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
484 field_name,
485 field,
486 new internal::RepeatedCustomValueConverter<NestedType>(
487 convert_func)));
488 }
489
490 template <class NestedType>
[email protected]193f946b2011-12-22 18:31:47491 void RegisterRepeatedMessage(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12492 ScopedVector<NestedType> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47493 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12494 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
[email protected]193f946b2011-12-22 18:31:47495 field_name,
496 field,
497 new internal::RepeatedMessageConverter<NestedType>));
498 }
499
[email protected]261c877e2012-01-05 09:46:42500 bool Convert(const base::Value& value, StructType* output) const {
[email protected]193f946b2011-12-22 18:31:47501 const DictionaryValue* dictionary_value = NULL;
502 if (!value.GetAsDictionary(&dictionary_value))
[email protected]261c877e2012-01-05 09:46:42503 return false;
[email protected]193f946b2011-12-22 18:31:47504
[email protected]a9b8e0a2012-01-14 05:36:12505 for(size_t i = 0; i < fields_.size(); ++i) {
[email protected]983b9b72012-01-27 07:12:21506 const internal::FieldConverterBase<StructType>* field_converter =
507 fields_[i];
[email protected]a61890e2012-07-27 22:27:11508 const base::Value* field = NULL;
[email protected]a9b8e0a2012-01-14 05:36:12509 if (dictionary_value->Get(field_converter->field_path(), &field)) {
510 if (!field_converter->ConvertField(*field, output)) {
511 DVLOG(1) << "failure at field " << field_converter->field_path();
[email protected]261c877e2012-01-05 09:46:42512 return false;
513 }
[email protected]193f946b2011-12-22 18:31:47514 }
515 }
[email protected]261c877e2012-01-05 09:46:42516 return true;
[email protected]193f946b2011-12-22 18:31:47517 }
518
519 private:
[email protected]983b9b72012-01-27 07:12:21520 ScopedVector<internal::FieldConverterBase<StructType> > fields_;
[email protected]193f946b2011-12-22 18:31:47521
522 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
523};
524
525} // namespace base
526
527#endif // BASE_JSON_JSON_VALUE_CONVERTER_H_