Add ICU message format support
[chromium-blink-merge.git] / base / json / json_value_converter.h
blobf94d46e3ccf71cbd7a19aeef0c608dcd17b14a06
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/base_export.h"
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_piece.h"
19 #include "base/values.h"
21 // JSONValueConverter converts a JSON value into a C++ struct in a
22 // lightweight way.
24 // Usage:
25 // For real examples, you may want to refer to _unittest.cc file.
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 // };
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 // }
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);
50 // 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.
56 // 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;
61 // static void RegisterJSONConverter(...) {
62 // ...
63 // converter->RegisterNestedField("foo", &Nested::foo);
64 // }
65 // };
67 // For repeated field, we just assume ScopedVector for its container
68 // and you can put RegisterRepeatedInt or some other types. Use
69 // RegisterRepeatedMessage for nested repeated fields.
71 // 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 // };
87 namespace base {
89 template <typename StructType>
90 class JSONValueConverter;
92 namespace internal {
94 template<typename StructType>
95 class FieldConverterBase {
96 public:
97 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;
101 const std::string& field_path() const { return field_path_; }
103 private:
104 std::string field_path_;
105 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
108 template <typename FieldType>
109 class ValueConverter {
110 public:
111 virtual ~ValueConverter() {}
112 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
115 template <typename StructType, typename FieldType>
116 class FieldConverter : public FieldConverterBase<StructType> {
117 public:
118 explicit FieldConverter(const std::string& path,
119 FieldType StructType::* field,
120 ValueConverter<FieldType>* converter)
121 : FieldConverterBase<StructType>(path),
122 field_pointer_(field),
123 value_converter_(converter) {
126 bool ConvertField(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 BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
141 public:
142 BasicValueConverter() {}
144 bool Convert(const base::Value& value, int* field) const override;
146 private:
147 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
150 template <>
151 class BASE_EXPORT BasicValueConverter<std::string>
152 : public ValueConverter<std::string> {
153 public:
154 BasicValueConverter() {}
156 bool Convert(const base::Value& value, std::string* field) const override;
158 private:
159 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
162 template <>
163 class BASE_EXPORT BasicValueConverter<string16>
164 : public ValueConverter<string16> {
165 public:
166 BasicValueConverter() {}
168 bool Convert(const base::Value& value, string16* field) const override;
170 private:
171 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
174 template <>
175 class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
176 public:
177 BasicValueConverter() {}
179 bool Convert(const base::Value& value, double* field) const override;
181 private:
182 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
185 template <>
186 class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
187 public:
188 BasicValueConverter() {}
190 bool Convert(const base::Value& value, bool* field) const override;
192 private:
193 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
196 template <typename FieldType>
197 class ValueFieldConverter : public ValueConverter<FieldType> {
198 public:
199 typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
201 ValueFieldConverter(ConvertFunc convert_func)
202 : convert_func_(convert_func) {}
204 bool Convert(const base::Value& value, FieldType* field) const override {
205 return convert_func_(&value, field);
208 private:
209 ConvertFunc convert_func_;
211 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
214 template <typename FieldType>
215 class CustomFieldConverter : public ValueConverter<FieldType> {
216 public:
217 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
219 CustomFieldConverter(ConvertFunc convert_func)
220 : convert_func_(convert_func) {}
222 bool Convert(const base::Value& value, FieldType* field) const override {
223 std::string string_value;
224 return value.GetAsString(&string_value) &&
225 convert_func_(string_value, field);
228 private:
229 ConvertFunc convert_func_;
231 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
234 template <typename NestedType>
235 class NestedValueConverter : public ValueConverter<NestedType> {
236 public:
237 NestedValueConverter() {}
239 bool Convert(const base::Value& value, NestedType* field) const override {
240 return converter_.Convert(value, field);
243 private:
244 JSONValueConverter<NestedType> converter_;
245 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
248 template <typename Element>
249 class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
250 public:
251 RepeatedValueConverter() {}
253 bool Convert(const base::Value& value,
254 ScopedVector<Element>* field) const override {
255 const base::ListValue* list = NULL;
256 if (!value.GetAsList(&list)) {
257 // The field is not a list.
258 return false;
261 field->reserve(list->GetSize());
262 for (size_t i = 0; i < list->GetSize(); ++i) {
263 const base::Value* element = NULL;
264 if (!list->Get(i, &element))
265 continue;
267 scoped_ptr<Element> e(new Element);
268 if (basic_converter_.Convert(*element, e.get())) {
269 field->push_back(e.release());
270 } else {
271 DVLOG(1) << "failure at " << i << "-th element";
272 return false;
275 return true;
278 private:
279 BasicValueConverter<Element> basic_converter_;
280 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
283 template <typename NestedType>
284 class RepeatedMessageConverter
285 : public ValueConverter<ScopedVector<NestedType> > {
286 public:
287 RepeatedMessageConverter() {}
289 bool Convert(const base::Value& value,
290 ScopedVector<NestedType>* field) const override {
291 const base::ListValue* list = NULL;
292 if (!value.GetAsList(&list))
293 return false;
295 field->reserve(list->GetSize());
296 for (size_t i = 0; i < list->GetSize(); ++i) {
297 const base::Value* element = NULL;
298 if (!list->Get(i, &element))
299 continue;
301 scoped_ptr<NestedType> nested(new NestedType);
302 if (converter_.Convert(*element, nested.get())) {
303 field->push_back(nested.release());
304 } else {
305 DVLOG(1) << "failure at " << i << "-th element";
306 return false;
309 return true;
312 private:
313 JSONValueConverter<NestedType> converter_;
314 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
317 template <typename NestedType>
318 class RepeatedCustomValueConverter
319 : public ValueConverter<ScopedVector<NestedType> > {
320 public:
321 typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
323 RepeatedCustomValueConverter(ConvertFunc convert_func)
324 : convert_func_(convert_func) {}
326 bool Convert(const base::Value& value,
327 ScopedVector<NestedType>* field) const override {
328 const base::ListValue* list = NULL;
329 if (!value.GetAsList(&list))
330 return false;
332 field->reserve(list->GetSize());
333 for (size_t i = 0; i < list->GetSize(); ++i) {
334 const base::Value* element = NULL;
335 if (!list->Get(i, &element))
336 continue;
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;
346 return true;
349 private:
350 ConvertFunc convert_func_;
351 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
355 } // namespace internal
357 template <class StructType>
358 class JSONValueConverter {
359 public:
360 JSONValueConverter() {
361 StructType::RegisterJSONConverter(this);
364 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>));
370 void RegisterStringField(const std::string& field_name,
371 std::string StructType::* field) {
372 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
373 field_name, field, new internal::BasicValueConverter<std::string>));
376 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>));
382 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>));
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>));
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>));
403 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)));
414 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)));
425 void RegisterRepeatedInt(const std::string& field_name,
426 ScopedVector<int> StructType::* field) {
427 fields_.push_back(
428 new internal::FieldConverter<StructType, ScopedVector<int> >(
429 field_name, field, new internal::RepeatedValueConverter<int>));
432 void RegisterRepeatedString(const std::string& field_name,
433 ScopedVector<std::string> StructType::* field) {
434 fields_.push_back(
435 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
436 field_name,
437 field,
438 new internal::RepeatedValueConverter<std::string>));
441 void RegisterRepeatedString(const std::string& field_name,
442 ScopedVector<string16> StructType::* field) {
443 fields_.push_back(
444 new internal::FieldConverter<StructType, ScopedVector<string16> >(
445 field_name,
446 field,
447 new internal::RepeatedValueConverter<string16>));
450 void RegisterRepeatedDouble(const std::string& field_name,
451 ScopedVector<double> StructType::* field) {
452 fields_.push_back(
453 new internal::FieldConverter<StructType, ScopedVector<double> >(
454 field_name, field, new internal::RepeatedValueConverter<double>));
457 void RegisterRepeatedBool(const std::string& field_name,
458 ScopedVector<bool> StructType::* field) {
459 fields_.push_back(
460 new internal::FieldConverter<StructType, ScopedVector<bool> >(
461 field_name, field, new internal::RepeatedValueConverter<bool>));
464 template <class NestedType>
465 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)));
477 template <class NestedType>
478 void RegisterRepeatedMessage(const std::string& field_name,
479 ScopedVector<NestedType> StructType::* field) {
480 fields_.push_back(
481 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
482 field_name,
483 field,
484 new internal::RepeatedMessageConverter<NestedType>));
487 bool Convert(const base::Value& value, StructType* output) const {
488 const DictionaryValue* dictionary_value = NULL;
489 if (!value.GetAsDictionary(&dictionary_value))
490 return false;
492 for(size_t i = 0; i < fields_.size(); ++i) {
493 const internal::FieldConverterBase<StructType>* field_converter =
494 fields_[i];
495 const base::Value* field = NULL;
496 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();
499 return false;
503 return true;
506 private:
507 ScopedVector<internal::FieldConverterBase<StructType> > fields_;
509 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
512 } // namespace base
514 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_