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.
4 
5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_
7 
8 #include <stddef.h>
9 
10 #include <string>
11 #include <vector>
12 
13 #include "base/base_export.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_piece.h"
21 #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 //
52 // 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 //
58 // 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;
63 //     static void RegisterJSONConverter(...) {
64 //       ...
65 //       converter->RegisterNestedField("foo", &Nested::foo);
66 //     }
67 //   };
68 //
69 // For repeated field, we just assume ScopedVector for its container
70 // and you can put RegisterRepeatedInt or some other types.  Use
71 // RegisterRepeatedMessage for nested repeated fields.
72 //
73 // 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 //   };
88 
89 namespace base {
90 
91 template <typename StructType>
92 class JSONValueConverter;
93 
94 namespace internal {
95 
96 template<typename StructType>
97 class FieldConverterBase {
98  public:
FieldConverterBase(const std::string & path)99   explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
~FieldConverterBase()100   virtual ~FieldConverterBase() {}
101   virtual bool ConvertField(const base::Value& value, StructType* obj)
102       const = 0;
field_path()103   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 
110 template <typename FieldType>
111 class ValueConverter {
112  public:
~ValueConverter()113   virtual ~ValueConverter() {}
114   virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
115 };
116 
117 template <typename StructType, typename FieldType>
118 class FieldConverter : public FieldConverterBase<StructType> {
119  public:
FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)120   explicit FieldConverter(const std::string& path,
121                           FieldType StructType::* field,
122                           ValueConverter<FieldType>* converter)
123       : FieldConverterBase<StructType>(path),
124         field_pointer_(field),
125         value_converter_(converter) {
126   }
127 
ConvertField(const base::Value & value,StructType * dst)128   bool ConvertField(const base::Value& value, StructType* dst) const override {
129     return value_converter_->Convert(value, &(dst->*field_pointer_));
130   }
131 
132  private:
133   FieldType StructType::* field_pointer_;
134   scoped_ptr<ValueConverter<FieldType> > value_converter_;
135   DISALLOW_COPY_AND_ASSIGN(FieldConverter);
136 };
137 
138 template <typename FieldType>
139 class BasicValueConverter;
140 
141 template <>
142 class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
143  public:
BasicValueConverter()144   BasicValueConverter() {}
145 
146   bool Convert(const base::Value& value, int* field) const override;
147 
148  private:
149   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
150 };
151 
152 template <>
153 class BASE_EXPORT BasicValueConverter<std::string>
154     : public ValueConverter<std::string> {
155  public:
BasicValueConverter()156   BasicValueConverter() {}
157 
158   bool Convert(const base::Value& value, std::string* field) const override;
159 
160  private:
161   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
162 };
163 
164 template <>
165 class BASE_EXPORT BasicValueConverter<string16>
166     : public ValueConverter<string16> {
167  public:
BasicValueConverter()168   BasicValueConverter() {}
169 
170   bool Convert(const base::Value& value, string16* field) const override;
171 
172  private:
173   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
174 };
175 
176 template <>
177 class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
178  public:
BasicValueConverter()179   BasicValueConverter() {}
180 
181   bool Convert(const base::Value& value, double* field) const override;
182 
183  private:
184   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
185 };
186 
187 template <>
188 class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
189  public:
BasicValueConverter()190   BasicValueConverter() {}
191 
192   bool Convert(const base::Value& value, bool* field) const override;
193 
194  private:
195   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
196 };
197 
198 template <typename FieldType>
199 class ValueFieldConverter : public ValueConverter<FieldType> {
200  public:
201   typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
202 
ValueFieldConverter(ConvertFunc convert_func)203   ValueFieldConverter(ConvertFunc convert_func)
204       : convert_func_(convert_func) {}
205 
Convert(const base::Value & value,FieldType * field)206   bool Convert(const base::Value& value, FieldType* field) const override {
207     return convert_func_(&value, field);
208   }
209 
210  private:
211   ConvertFunc convert_func_;
212 
213   DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
214 };
215 
216 template <typename FieldType>
217 class CustomFieldConverter : public ValueConverter<FieldType> {
218  public:
219   typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
220 
CustomFieldConverter(ConvertFunc convert_func)221   CustomFieldConverter(ConvertFunc convert_func)
222       : convert_func_(convert_func) {}
223 
Convert(const base::Value & value,FieldType * field)224   bool Convert(const base::Value& value, FieldType* field) const override {
225     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 
236 template <typename NestedType>
237 class NestedValueConverter : public ValueConverter<NestedType> {
238  public:
NestedValueConverter()239   NestedValueConverter() {}
240 
Convert(const base::Value & value,NestedType * field)241   bool Convert(const base::Value& value, NestedType* field) const override {
242     return converter_.Convert(value, field);
243   }
244 
245  private:
246   JSONValueConverter<NestedType> converter_;
247   DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
248 };
249 
250 template <typename Element>
251 class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
252  public:
RepeatedValueConverter()253   RepeatedValueConverter() {}
254 
Convert(const base::Value & value,ScopedVector<Element> * field)255   bool Convert(const base::Value& value,
256                ScopedVector<Element>* field) const override {
257     const base::ListValue* list = NULL;
258     if (!value.GetAsList(&list)) {
259       // The field is not a list.
260       return false;
261     }
262 
263     field->reserve(list->GetSize());
264     for (size_t i = 0; i < list->GetSize(); ++i) {
265       const base::Value* element = NULL;
266       if (!list->Get(i, &element))
267         continue;
268 
269       scoped_ptr<Element> e(new Element);
270       if (basic_converter_.Convert(*element, e.get())) {
271         field->push_back(e.release());
272       } else {
273         DVLOG(1) << "failure at " << i << "-th element";
274         return false;
275       }
276     }
277     return true;
278   }
279 
280  private:
281   BasicValueConverter<Element> basic_converter_;
282   DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
283 };
284 
285 template <typename NestedType>
286 class RepeatedMessageConverter
287     : public ValueConverter<ScopedVector<NestedType> > {
288  public:
RepeatedMessageConverter()289   RepeatedMessageConverter() {}
290 
Convert(const base::Value & value,ScopedVector<NestedType> * field)291   bool Convert(const base::Value& value,
292                ScopedVector<NestedType>* field) const override {
293     const base::ListValue* list = NULL;
294     if (!value.GetAsList(&list))
295       return false;
296 
297     field->reserve(list->GetSize());
298     for (size_t i = 0; i < list->GetSize(); ++i) {
299       const base::Value* element = NULL;
300       if (!list->Get(i, &element))
301         continue;
302 
303       scoped_ptr<NestedType> nested(new NestedType);
304       if (converter_.Convert(*element, nested.get())) {
305         field->push_back(nested.release());
306       } else {
307         DVLOG(1) << "failure at " << i << "-th element";
308         return false;
309       }
310     }
311     return true;
312   }
313 
314  private:
315   JSONValueConverter<NestedType> converter_;
316   DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
317 };
318 
319 template <typename NestedType>
320 class RepeatedCustomValueConverter
321     : public ValueConverter<ScopedVector<NestedType> > {
322  public:
323   typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
324 
RepeatedCustomValueConverter(ConvertFunc convert_func)325   RepeatedCustomValueConverter(ConvertFunc convert_func)
326       : convert_func_(convert_func) {}
327 
Convert(const base::Value & value,ScopedVector<NestedType> * field)328   bool Convert(const base::Value& value,
329                ScopedVector<NestedType>* field) const override {
330     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) {
336       const base::Value* element = NULL;
337       if (!list->Get(i, &element))
338         continue;
339 
340       scoped_ptr<NestedType> nested(new NestedType);
341       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 
357 }  // namespace internal
358 
359 template <class StructType>
360 class JSONValueConverter {
361  public:
JSONValueConverter()362   JSONValueConverter() {
363     StructType::RegisterJSONConverter(this);
364   }
365 
RegisterIntField(const std::string & field_name,int StructType::* field)366   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 
RegisterStringField(const std::string & field_name,std::string StructType::* field)372   void RegisterStringField(const std::string& field_name,
373                            std::string StructType::* field) {
374     fields_.push_back(new internal::FieldConverter<StructType, std::string>(
375         field_name, field, new internal::BasicValueConverter<std::string>));
376   }
377 
RegisterStringField(const std::string & field_name,string16 StructType::* field)378   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 
RegisterBoolField(const std::string & field_name,bool StructType::* field)384   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 
RegisterDoubleField(const std::string & field_name,double StructType::* field)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>
RegisterNestedField(const std::string & field_name,NestedType StructType::* field)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 
405   template <typename FieldType>
RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const StringPiece &,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 
416   template <typename FieldType>
RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,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 
RegisterRepeatedInt(const std::string & field_name,ScopedVector<int> StructType::* field)427   void RegisterRepeatedInt(const std::string& field_name,
428                            ScopedVector<int> StructType::* field) {
429     fields_.push_back(
430         new internal::FieldConverter<StructType, ScopedVector<int> >(
431             field_name, field, new internal::RepeatedValueConverter<int>));
432   }
433 
RegisterRepeatedString(const std::string & field_name,ScopedVector<std::string> StructType::* field)434   void RegisterRepeatedString(const std::string& field_name,
435                               ScopedVector<std::string> StructType::* field) {
436     fields_.push_back(
437         new internal::FieldConverter<StructType, ScopedVector<std::string> >(
438             field_name,
439             field,
440             new internal::RepeatedValueConverter<std::string>));
441   }
442 
RegisterRepeatedString(const std::string & field_name,ScopedVector<string16> StructType::* field)443   void RegisterRepeatedString(const std::string& field_name,
444                               ScopedVector<string16> StructType::* field) {
445     fields_.push_back(
446         new internal::FieldConverter<StructType, ScopedVector<string16> >(
447             field_name,
448             field,
449             new internal::RepeatedValueConverter<string16>));
450   }
451 
RegisterRepeatedDouble(const std::string & field_name,ScopedVector<double> StructType::* field)452   void RegisterRepeatedDouble(const std::string& field_name,
453                               ScopedVector<double> StructType::* field) {
454     fields_.push_back(
455         new internal::FieldConverter<StructType, ScopedVector<double> >(
456             field_name, field, new internal::RepeatedValueConverter<double>));
457   }
458 
RegisterRepeatedBool(const std::string & field_name,ScopedVector<bool> StructType::* field)459   void RegisterRepeatedBool(const std::string& field_name,
460                             ScopedVector<bool> StructType::* field) {
461     fields_.push_back(
462         new internal::FieldConverter<StructType, ScopedVector<bool> >(
463             field_name, field, new internal::RepeatedValueConverter<bool>));
464   }
465 
466   template <class NestedType>
RegisterRepeatedCustomValue(const std::string & field_name,ScopedVector<NestedType> StructType::* field,bool (* convert_func)(const base::Value *,NestedType *))467   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>
RegisterRepeatedMessage(const std::string & field_name,ScopedVector<NestedType> StructType::* field)480   void RegisterRepeatedMessage(const std::string& field_name,
481                                ScopedVector<NestedType> StructType::* field) {
482     fields_.push_back(
483         new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
484             field_name,
485             field,
486             new internal::RepeatedMessageConverter<NestedType>));
487   }
488 
Convert(const base::Value & value,StructType * output)489   bool Convert(const base::Value& value, StructType* output) const {
490     const DictionaryValue* dictionary_value = NULL;
491     if (!value.GetAsDictionary(&dictionary_value))
492       return false;
493 
494     for(size_t i = 0; i < fields_.size(); ++i) {
495       const internal::FieldConverterBase<StructType>* field_converter =
496           fields_[i];
497       const base::Value* field = NULL;
498       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();
501           return false;
502         }
503       }
504     }
505     return true;
506   }
507 
508  private:
509   ScopedVector<internal::FieldConverterBase<StructType> > fields_;
510 
511   DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
512 };
513 
514 }  // namespace base
515 
516 #endif  // BASE_JSON_JSON_VALUE_CONVERTER_H_
517