Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / base / json / json_value_converter.h
blobcf3c74f0c7599a2d074ae9c2408a74a85f277100
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_
8 #include <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_piece.h"
18 #include "base/values.h"
20 // JSONValueConverter converts a JSON value into a C++ struct in a
21 // lightweight way.
23 // Usage:
24 // For real examples, you may want to refer to _unittest.cc file.
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 // };
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 // }
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);
49 // 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.
55 // 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;
60 // static void RegisterJSONConverter(...) {
61 // ...
62 // converter->RegisterNestedField("foo", &Nested::foo);
63 // }
64 // };
66 // For repeated field, we just assume ScopedVector for its container
67 // and you can put RegisterRepeatedInt or some other types. Use
68 // RegisterRepeatedMessage for nested repeated fields.
70 // 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 // };
86 namespace base {
88 template <typename StructType>
89 class JSONValueConverter;
91 namespace internal {
93 template<typename StructType>
94 class FieldConverterBase {
95 public:
96 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;
100 const std::string& field_path() const { return field_path_; }
102 private:
103 std::string field_path_;
104 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
107 template <typename FieldType>
108 class ValueConverter {
109 public:
110 virtual ~ValueConverter() {}
111 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
114 template <typename StructType, typename FieldType>
115 class FieldConverter : public FieldConverterBase<StructType> {
116 public:
117 explicit FieldConverter(const std::string& path,
118 FieldType StructType::* field,
119 ValueConverter<FieldType>* converter)
120 : FieldConverterBase<StructType>(path),
121 field_pointer_(field),
122 value_converter_(converter) {
125 virtual bool ConvertField(
126 const base::Value& value, StructType* dst) const OVERRIDE {
127 return value_converter_->Convert(value, &(dst->*field_pointer_));
130 private:
131 FieldType StructType::* field_pointer_;
132 scoped_ptr<ValueConverter<FieldType> > value_converter_;
133 DISALLOW_COPY_AND_ASSIGN(FieldConverter);
136 template <typename FieldType>
137 class BasicValueConverter;
139 template <>
140 class BasicValueConverter<int> : public ValueConverter<int> {
141 public:
142 BasicValueConverter() {}
144 virtual bool Convert(const base::Value& value, int* field) const OVERRIDE {
145 return value.GetAsInteger(field);
148 private:
149 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
152 template <>
153 class BasicValueConverter<std::string> : public ValueConverter<std::string> {
154 public:
155 BasicValueConverter() {}
157 virtual bool Convert(
158 const base::Value& value, std::string* field) const OVERRIDE {
159 return value.GetAsString(field);
162 private:
163 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
166 template <>
167 class BasicValueConverter<string16> : public ValueConverter<string16> {
168 public:
169 BasicValueConverter() {}
171 virtual bool Convert(
172 const base::Value& value, string16* field) const OVERRIDE {
173 return value.GetAsString(field);
176 private:
177 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
180 template <>
181 class BasicValueConverter<double> : public ValueConverter<double> {
182 public:
183 BasicValueConverter() {}
185 virtual bool Convert(const base::Value& value, double* field) const OVERRIDE {
186 return value.GetAsDouble(field);
189 private:
190 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
193 template <>
194 class BasicValueConverter<bool> : public ValueConverter<bool> {
195 public:
196 BasicValueConverter() {}
198 virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE {
199 return value.GetAsBoolean(field);
202 private:
203 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
206 template <typename FieldType>
207 class ValueFieldConverter : public ValueConverter<FieldType> {
208 public:
209 typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
211 ValueFieldConverter(ConvertFunc convert_func)
212 : convert_func_(convert_func) {}
214 virtual bool Convert(const base::Value& value,
215 FieldType* field) const OVERRIDE {
216 return convert_func_(&value, field);
219 private:
220 ConvertFunc convert_func_;
222 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
225 template <typename FieldType>
226 class CustomFieldConverter : public ValueConverter<FieldType> {
227 public:
228 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
230 CustomFieldConverter(ConvertFunc convert_func)
231 : convert_func_(convert_func) {}
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);
240 private:
241 ConvertFunc convert_func_;
243 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
246 template <typename NestedType>
247 class NestedValueConverter : public ValueConverter<NestedType> {
248 public:
249 NestedValueConverter() {}
251 virtual bool Convert(
252 const base::Value& value, NestedType* field) const OVERRIDE {
253 return converter_.Convert(value, field);
256 private:
257 JSONValueConverter<NestedType> converter_;
258 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
261 template <typename Element>
262 class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
263 public:
264 RepeatedValueConverter() {}
266 virtual bool Convert(
267 const base::Value& value, ScopedVector<Element>* field) const OVERRIDE {
268 const base::ListValue* list = NULL;
269 if (!value.GetAsList(&list)) {
270 // The field is not a list.
271 return false;
274 field->reserve(list->GetSize());
275 for (size_t i = 0; i < list->GetSize(); ++i) {
276 const base::Value* element = NULL;
277 if (!list->Get(i, &element))
278 continue;
280 scoped_ptr<Element> e(new Element);
281 if (basic_converter_.Convert(*element, e.get())) {
282 field->push_back(e.release());
283 } else {
284 DVLOG(1) << "failure at " << i << "-th element";
285 return false;
288 return true;
291 private:
292 BasicValueConverter<Element> basic_converter_;
293 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
296 template <typename NestedType>
297 class RepeatedMessageConverter
298 : public ValueConverter<ScopedVector<NestedType> > {
299 public:
300 RepeatedMessageConverter() {}
302 virtual bool Convert(const base::Value& value,
303 ScopedVector<NestedType>* field) const OVERRIDE {
304 const base::ListValue* list = NULL;
305 if (!value.GetAsList(&list))
306 return false;
308 field->reserve(list->GetSize());
309 for (size_t i = 0; i < list->GetSize(); ++i) {
310 const base::Value* element = NULL;
311 if (!list->Get(i, &element))
312 continue;
314 scoped_ptr<NestedType> nested(new NestedType);
315 if (converter_.Convert(*element, nested.get())) {
316 field->push_back(nested.release());
317 } else {
318 DVLOG(1) << "failure at " << i << "-th element";
319 return false;
322 return true;
325 private:
326 JSONValueConverter<NestedType> converter_;
327 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
330 template <typename NestedType>
331 class RepeatedCustomValueConverter
332 : public ValueConverter<ScopedVector<NestedType> > {
333 public:
334 typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
336 RepeatedCustomValueConverter(ConvertFunc convert_func)
337 : convert_func_(convert_func) {}
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;
345 field->reserve(list->GetSize());
346 for (size_t i = 0; i < list->GetSize(); ++i) {
347 const base::Value* element = NULL;
348 if (!list->Get(i, &element))
349 continue;
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;
359 return true;
362 private:
363 ConvertFunc convert_func_;
364 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
368 } // namespace internal
370 template <class StructType>
371 class JSONValueConverter {
372 public:
373 JSONValueConverter() {
374 StructType::RegisterJSONConverter(this);
377 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>));
383 void RegisterStringField(const std::string& field_name,
384 std::string StructType::* field) {
385 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
386 field_name, field, new internal::BasicValueConverter<std::string>));
389 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>));
395 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>));
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>));
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>));
416 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)));
427 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)));
438 void RegisterRepeatedInt(const std::string& field_name,
439 ScopedVector<int> StructType::* field) {
440 fields_.push_back(
441 new internal::FieldConverter<StructType, ScopedVector<int> >(
442 field_name, field, new internal::RepeatedValueConverter<int>));
445 void RegisterRepeatedString(const std::string& field_name,
446 ScopedVector<std::string> StructType::* field) {
447 fields_.push_back(
448 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
449 field_name,
450 field,
451 new internal::RepeatedValueConverter<std::string>));
454 void RegisterRepeatedString(const std::string& field_name,
455 ScopedVector<string16> StructType::* field) {
456 fields_.push_back(
457 new internal::FieldConverter<StructType, ScopedVector<string16> >(
458 field_name,
459 field,
460 new internal::RepeatedValueConverter<string16>));
463 void RegisterRepeatedDouble(const std::string& field_name,
464 ScopedVector<double> StructType::* field) {
465 fields_.push_back(
466 new internal::FieldConverter<StructType, ScopedVector<double> >(
467 field_name, field, new internal::RepeatedValueConverter<double>));
470 void RegisterRepeatedBool(const std::string& field_name,
471 ScopedVector<bool> StructType::* field) {
472 fields_.push_back(
473 new internal::FieldConverter<StructType, ScopedVector<bool> >(
474 field_name, field, new internal::RepeatedValueConverter<bool>));
477 template <class NestedType>
478 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)));
490 template <class NestedType>
491 void RegisterRepeatedMessage(const std::string& field_name,
492 ScopedVector<NestedType> StructType::* field) {
493 fields_.push_back(
494 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
495 field_name,
496 field,
497 new internal::RepeatedMessageConverter<NestedType>));
500 bool Convert(const base::Value& value, StructType* output) const {
501 const DictionaryValue* dictionary_value = NULL;
502 if (!value.GetAsDictionary(&dictionary_value))
503 return false;
505 for(size_t i = 0; i < fields_.size(); ++i) {
506 const internal::FieldConverterBase<StructType>* field_converter =
507 fields_[i];
508 const base::Value* field = NULL;
509 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();
512 return false;
516 return true;
519 private:
520 ScopedVector<internal::FieldConverterBase<StructType> > fields_;
522 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
525 } // namespace base
527 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_