• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
9 #include <vector>
10 
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"
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 //
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.
54 //
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 //   };
65 //
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.
69 //
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 //   };
85 
86 namespace base {
87 
88 template <typename StructType>
89 class JSONValueConverter;
90 
91 namespace internal {
92 
93 template<typename StructType>
94 class FieldConverterBase {
95  public:
FieldConverterBase(const std::string & path)96   explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
~FieldConverterBase()97   virtual ~FieldConverterBase() {}
98   virtual bool ConvertField(const base::Value& value, StructType* obj)
99       const = 0;
field_path()100   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 
107 template <typename FieldType>
108 class ValueConverter {
109  public:
~ValueConverter()110   virtual ~ValueConverter() {}
111   virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
112 };
113 
114 template <typename StructType, typename FieldType>
115 class FieldConverter : public FieldConverterBase<StructType> {
116  public:
FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)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) {
123   }
124 
ConvertField(const base::Value & value,StructType * dst)125   virtual bool ConvertField(
126       const base::Value& value, StructType* dst) const OVERRIDE {
127     return value_converter_->Convert(value, &(dst->*field_pointer_));
128   }
129 
130  private:
131   FieldType StructType::* field_pointer_;
132   scoped_ptr<ValueConverter<FieldType> > value_converter_;
133   DISALLOW_COPY_AND_ASSIGN(FieldConverter);
134 };
135 
136 template <typename FieldType>
137 class BasicValueConverter;
138 
139 template <>
140 class BasicValueConverter<int> : public ValueConverter<int> {
141  public:
BasicValueConverter()142   BasicValueConverter() {}
143 
Convert(const base::Value & value,int * field)144   virtual bool Convert(const base::Value& value, int* field) const OVERRIDE {
145     return value.GetAsInteger(field);
146   }
147 
148  private:
149   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
150 };
151 
152 template <>
153 class BasicValueConverter<std::string> : public ValueConverter<std::string> {
154  public:
BasicValueConverter()155   BasicValueConverter() {}
156 
Convert(const base::Value & value,std::string * field)157   virtual bool Convert(
158       const base::Value& value, std::string* field) const OVERRIDE {
159     return value.GetAsString(field);
160   }
161 
162  private:
163   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
164 };
165 
166 template <>
167 class BasicValueConverter<string16> : public ValueConverter<string16> {
168  public:
BasicValueConverter()169   BasicValueConverter() {}
170 
Convert(const base::Value & value,string16 * field)171   virtual bool Convert(
172       const base::Value& value, string16* field) const OVERRIDE {
173     return value.GetAsString(field);
174   }
175 
176  private:
177   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
178 };
179 
180 template <>
181 class BasicValueConverter<double> : public ValueConverter<double> {
182  public:
BasicValueConverter()183   BasicValueConverter() {}
184 
Convert(const base::Value & value,double * field)185   virtual bool Convert(const base::Value& value, double* field) const OVERRIDE {
186     return value.GetAsDouble(field);
187   }
188 
189  private:
190   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
191 };
192 
193 template <>
194 class BasicValueConverter<bool> : public ValueConverter<bool> {
195  public:
BasicValueConverter()196   BasicValueConverter() {}
197 
Convert(const base::Value & value,bool * field)198   virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE {
199     return value.GetAsBoolean(field);
200   }
201 
202  private:
203   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
204 };
205 
206 template <typename FieldType>
207 class ValueFieldConverter : public ValueConverter<FieldType> {
208  public:
209   typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
210 
ValueFieldConverter(ConvertFunc convert_func)211   ValueFieldConverter(ConvertFunc convert_func)
212       : convert_func_(convert_func) {}
213 
Convert(const base::Value & value,FieldType * field)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 
225 template <typename FieldType>
226 class CustomFieldConverter : public ValueConverter<FieldType> {
227  public:
228   typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
229 
CustomFieldConverter(ConvertFunc convert_func)230   CustomFieldConverter(ConvertFunc convert_func)
231       : convert_func_(convert_func) {}
232 
Convert(const base::Value & value,FieldType * field)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 
246 template <typename NestedType>
247 class NestedValueConverter : public ValueConverter<NestedType> {
248  public:
NestedValueConverter()249   NestedValueConverter() {}
250 
Convert(const base::Value & value,NestedType * field)251   virtual bool Convert(
252       const base::Value& value, NestedType* field) const OVERRIDE {
253     return converter_.Convert(value, field);
254   }
255 
256  private:
257   JSONValueConverter<NestedType> converter_;
258   DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
259 };
260 
261 template <typename Element>
262 class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
263  public:
RepeatedValueConverter()264   RepeatedValueConverter() {}
265 
Convert(const base::Value & value,ScopedVector<Element> * field)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;
272     }
273 
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;
279 
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;
286       }
287     }
288     return true;
289   }
290 
291  private:
292   BasicValueConverter<Element> basic_converter_;
293   DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
294 };
295 
296 template <typename NestedType>
297 class RepeatedMessageConverter
298     : public ValueConverter<ScopedVector<NestedType> > {
299  public:
RepeatedMessageConverter()300   RepeatedMessageConverter() {}
301 
Convert(const base::Value & value,ScopedVector<NestedType> * field)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;
307 
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;
313 
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;
320       }
321     }
322     return true;
323   }
324 
325  private:
326   JSONValueConverter<NestedType> converter_;
327   DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
328 };
329 
330 template <typename NestedType>
331 class RepeatedCustomValueConverter
332     : public ValueConverter<ScopedVector<NestedType> > {
333  public:
334   typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
335 
RepeatedCustomValueConverter(ConvertFunc convert_func)336   RepeatedCustomValueConverter(ConvertFunc convert_func)
337       : convert_func_(convert_func) {}
338 
Convert(const base::Value & value,ScopedVector<NestedType> * field)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) {
347       const base::Value* element = NULL;
348       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 
368 }  // namespace internal
369 
370 template <class StructType>
371 class JSONValueConverter {
372  public:
JSONValueConverter()373   JSONValueConverter() {
374     StructType::RegisterJSONConverter(this);
375   }
376 
RegisterIntField(const std::string & field_name,int StructType::* field)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>));
381   }
382 
RegisterStringField(const std::string & field_name,std::string StructType::* field)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>));
387   }
388 
RegisterStringField(const std::string & field_name,string16 StructType::* field)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>));
393   }
394 
RegisterBoolField(const std::string & field_name,bool StructType::* field)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>));
399   }
400 
RegisterDoubleField(const std::string & field_name,double StructType::* field)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>
RegisterNestedField(const std::string & field_name,NestedType StructType::* field)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 
416   template <typename FieldType>
RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const StringPiece &,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 
427   template <typename FieldType>
RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,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 
RegisterRepeatedInt(const std::string & field_name,ScopedVector<int> StructType::* field)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>));
443   }
444 
RegisterRepeatedString(const std::string & field_name,ScopedVector<std::string> StructType::* field)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>));
452   }
453 
RegisterRepeatedString(const std::string & field_name,ScopedVector<string16> StructType::* field)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>));
461   }
462 
RegisterRepeatedDouble(const std::string & field_name,ScopedVector<double> StructType::* field)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>));
468   }
469 
RegisterRepeatedBool(const std::string & field_name,ScopedVector<bool> StructType::* field)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>));
475   }
476 
477   template <class NestedType>
RegisterRepeatedCustomValue(const std::string & field_name,ScopedVector<NestedType> StructType::* field,bool (* convert_func)(const base::Value *,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)));
488   }
489 
490   template <class NestedType>
RegisterRepeatedMessage(const std::string & field_name,ScopedVector<NestedType> StructType::* field)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>));
498   }
499 
Convert(const base::Value & value,StructType * output)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;
504 
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;
513         }
514       }
515     }
516     return true;
517   }
518 
519  private:
520   ScopedVector<internal::FieldConverterBase<StructType> > fields_;
521 
522   DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
523 };
524 
525 }  // namespace base
526 
527 #endif  // BASE_JSON_JSON_VALUE_CONVERTER_H_
528