• 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 <stddef.h>
9 
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "base/base_export.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_piece.h"
20 #include "base/values.h"
21 
22 // JSONValueConverter converts a JSON value into a C++ struct in a
23 // lightweight way.
24 //
25 // Usage:
26 // For real examples, you may want to refer to _unittest.cc file.
27 //
28 // Assume that you have a struct like this:
29 //   struct Message {
30 //     int foo;
31 //     std::string bar;
32 //     static void RegisterJSONConverter(
33 //         JSONValueConverter<Message>* converter);
34 //   };
35 //
36 // And you want to parse a json data into this struct.  First, you
37 // need to declare RegisterJSONConverter() method in your struct.
38 //   // static
39 //   void Message::RegisterJSONConverter(
40 //       JSONValueConverter<Message>* converter) {
41 //     converter->RegisterIntField("foo", &Message::foo);
42 //     converter->RegisterStringField("bar", &Message::bar);
43 //   }
44 //
45 // Then, you just instantiate your JSONValueConverter of your type and call
46 // Convert() method.
47 //   Message message;
48 //   JSONValueConverter<Message> converter;
49 //   converter.Convert(json, &message);
50 //
51 // Convert() returns false when it fails.  Here "fail" means that the value is
52 // structurally different from expected, such like a string value appears
53 // for an int field.  Do not report failures for missing fields.
54 // Also note that Convert() will modify the passed |message| even when it
55 // fails for performance reason.
56 //
57 // For nested field, the internal message also has to implement the registration
58 // method.  Then, just use RegisterNestedField() from the containing struct's
59 // RegisterJSONConverter method.
60 //   struct Nested {
61 //     Message foo;
62 //     static void RegisterJSONConverter(...) {
63 //       ...
64 //       converter->RegisterNestedField("foo", &Nested::foo);
65 //     }
66 //   };
67 //
68 // For repeated field, we just assume std::vector<std::unique_ptr<ElementType>>
69 // for its container and you can put RegisterRepeatedInt or some other types.
70 // Use RegisterRepeatedMessage for nested repeated fields.
71 //
72 // Sometimes JSON format uses string representations for other types such
73 // like enum, timestamp, or URL.  You can use RegisterCustomField method
74 // and specify a function to convert a StringPiece to your type.
75 //   bool ConvertFunc(const StringPiece& s, YourEnum* result) {
76 //     // do something and return true if succeed...
77 //   }
78 //   struct Message {
79 //     YourEnum ye;
80 //     ...
81 //     static void RegisterJSONConverter(...) {
82 //       ...
83 //       converter->RegsiterCustomField<YourEnum>(
84 //           "your_enum", &Message::ye, &ConvertFunc);
85 //     }
86 //   };
87 
88 namespace base {
89 
90 template <typename StructType>
91 class JSONValueConverter;
92 
93 namespace internal {
94 
95 template<typename StructType>
96 class FieldConverterBase {
97  public:
FieldConverterBase(const std::string & path)98   explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
~FieldConverterBase()99   virtual ~FieldConverterBase() {}
100   virtual bool ConvertField(const base::Value& value, StructType* obj)
101       const = 0;
field_path()102   const std::string& field_path() const { return field_path_; }
103 
104  private:
105   std::string field_path_;
106   DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
107 };
108 
109 template <typename FieldType>
110 class ValueConverter {
111  public:
~ValueConverter()112   virtual ~ValueConverter() {}
113   virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
114 };
115 
116 template <typename StructType, typename FieldType>
117 class FieldConverter : public FieldConverterBase<StructType> {
118  public:
FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)119   explicit FieldConverter(const std::string& path,
120                           FieldType StructType::* field,
121                           ValueConverter<FieldType>* converter)
122       : FieldConverterBase<StructType>(path),
123         field_pointer_(field),
124         value_converter_(converter) {
125   }
126 
ConvertField(const base::Value & value,StructType * dst)127   bool ConvertField(const base::Value& value, StructType* dst) const override {
128     return value_converter_->Convert(value, &(dst->*field_pointer_));
129   }
130 
131  private:
132   FieldType StructType::* field_pointer_;
133   std::unique_ptr<ValueConverter<FieldType>> value_converter_;
134   DISALLOW_COPY_AND_ASSIGN(FieldConverter);
135 };
136 
137 template <typename FieldType>
138 class BasicValueConverter;
139 
140 template <>
141 class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
142  public:
BasicValueConverter()143   BasicValueConverter() {}
144 
145   bool Convert(const base::Value& value, int* field) const override;
146 
147  private:
148   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
149 };
150 
151 template <>
152 class BASE_EXPORT BasicValueConverter<std::string>
153     : public ValueConverter<std::string> {
154  public:
BasicValueConverter()155   BasicValueConverter() {}
156 
157   bool Convert(const base::Value& value, std::string* field) const override;
158 
159  private:
160   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
161 };
162 
163 template <>
164 class BASE_EXPORT BasicValueConverter<string16>
165     : public ValueConverter<string16> {
166  public:
BasicValueConverter()167   BasicValueConverter() {}
168 
169   bool Convert(const base::Value& value, string16* field) const override;
170 
171  private:
172   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
173 };
174 
175 template <>
176 class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
177  public:
BasicValueConverter()178   BasicValueConverter() {}
179 
180   bool Convert(const base::Value& value, double* field) const override;
181 
182  private:
183   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
184 };
185 
186 template <>
187 class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
188  public:
BasicValueConverter()189   BasicValueConverter() {}
190 
191   bool Convert(const base::Value& value, bool* field) const override;
192 
193  private:
194   DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
195 };
196 
197 template <typename FieldType>
198 class ValueFieldConverter : public ValueConverter<FieldType> {
199  public:
200   typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
201 
ValueFieldConverter(ConvertFunc convert_func)202   explicit ValueFieldConverter(ConvertFunc convert_func)
203       : convert_func_(convert_func) {}
204 
Convert(const base::Value & value,FieldType * field)205   bool Convert(const base::Value& value, FieldType* field) const override {
206     return convert_func_(&value, field);
207   }
208 
209  private:
210   ConvertFunc convert_func_;
211 
212   DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
213 };
214 
215 template <typename FieldType>
216 class CustomFieldConverter : public ValueConverter<FieldType> {
217  public:
218   typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
219 
CustomFieldConverter(ConvertFunc convert_func)220   explicit CustomFieldConverter(ConvertFunc convert_func)
221       : convert_func_(convert_func) {}
222 
Convert(const base::Value & value,FieldType * field)223   bool Convert(const base::Value& value, FieldType* field) const override {
224     std::string string_value;
225     return value.GetAsString(&string_value) &&
226         convert_func_(string_value, field);
227   }
228 
229  private:
230   ConvertFunc convert_func_;
231 
232   DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
233 };
234 
235 template <typename NestedType>
236 class NestedValueConverter : public ValueConverter<NestedType> {
237  public:
NestedValueConverter()238   NestedValueConverter() {}
239 
Convert(const base::Value & value,NestedType * field)240   bool Convert(const base::Value& value, NestedType* field) const override {
241     return converter_.Convert(value, field);
242   }
243 
244  private:
245   JSONValueConverter<NestedType> converter_;
246   DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
247 };
248 
249 template <typename Element>
250 class RepeatedValueConverter
251     : public ValueConverter<std::vector<std::unique_ptr<Element>>> {
252  public:
RepeatedValueConverter()253   RepeatedValueConverter() {}
254 
Convert(const base::Value & value,std::vector<std::unique_ptr<Element>> * field)255   bool Convert(const base::Value& value,
256                std::vector<std::unique_ptr<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       std::unique_ptr<Element> e(new Element);
270       if (basic_converter_.Convert(*element, e.get())) {
271         field->push_back(std::move(e));
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<std::vector<std::unique_ptr<NestedType>>> {
288  public:
RepeatedMessageConverter()289   RepeatedMessageConverter() {}
290 
Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)291   bool Convert(const base::Value& value,
292                std::vector<std::unique_ptr<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       std::unique_ptr<NestedType> nested(new NestedType);
304       if (converter_.Convert(*element, nested.get())) {
305         field->push_back(std::move(nested));
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<std::vector<std::unique_ptr<NestedType>>> {
322  public:
323   typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
324 
RepeatedCustomValueConverter(ConvertFunc convert_func)325   explicit RepeatedCustomValueConverter(ConvertFunc convert_func)
326       : convert_func_(convert_func) {}
327 
Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)328   bool Convert(const base::Value& value,
329                std::vector<std::unique_ptr<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       std::unique_ptr<NestedType> nested(new NestedType);
341       if ((*convert_func_)(element, nested.get())) {
342         field->push_back(std::move(nested));
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(MakeUnique<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(
375         MakeUnique<internal::FieldConverter<StructType, std::string>>(
376             field_name, field, new internal::BasicValueConverter<std::string>));
377   }
378 
RegisterStringField(const std::string & field_name,string16 StructType::* field)379   void RegisterStringField(const std::string& field_name,
380                            string16 StructType::* field) {
381     fields_.push_back(
382         MakeUnique<internal::FieldConverter<StructType, string16>>(
383             field_name, field, new internal::BasicValueConverter<string16>));
384   }
385 
RegisterBoolField(const std::string & field_name,bool StructType::* field)386   void RegisterBoolField(const std::string& field_name,
387                          bool StructType::* field) {
388     fields_.push_back(MakeUnique<internal::FieldConverter<StructType, bool>>(
389         field_name, field, new internal::BasicValueConverter<bool>));
390   }
391 
RegisterDoubleField(const std::string & field_name,double StructType::* field)392   void RegisterDoubleField(const std::string& field_name,
393                            double StructType::* field) {
394     fields_.push_back(MakeUnique<internal::FieldConverter<StructType, double>>(
395         field_name, field, new internal::BasicValueConverter<double>));
396   }
397 
398   template <class NestedType>
RegisterNestedField(const std::string & field_name,NestedType StructType::* field)399   void RegisterNestedField(
400       const std::string& field_name, NestedType StructType::* field) {
401     fields_.push_back(
402         MakeUnique<internal::FieldConverter<StructType, NestedType>>(
403             field_name, field, new internal::NestedValueConverter<NestedType>));
404   }
405 
406   template <typename FieldType>
RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const StringPiece &,FieldType *))407   void RegisterCustomField(
408       const std::string& field_name,
409       FieldType StructType::* field,
410       bool (*convert_func)(const StringPiece&, FieldType*)) {
411     fields_.push_back(
412         MakeUnique<internal::FieldConverter<StructType, FieldType>>(
413             field_name, field,
414             new internal::CustomFieldConverter<FieldType>(convert_func)));
415   }
416 
417   template <typename FieldType>
RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,FieldType *))418   void RegisterCustomValueField(
419       const std::string& field_name,
420       FieldType StructType::* field,
421       bool (*convert_func)(const base::Value*, FieldType*)) {
422     fields_.push_back(
423         MakeUnique<internal::FieldConverter<StructType, FieldType>>(
424             field_name, field,
425             new internal::ValueFieldConverter<FieldType>(convert_func)));
426   }
427 
RegisterRepeatedInt(const std::string & field_name,std::vector<std::unique_ptr<int>> StructType::* field)428   void RegisterRepeatedInt(
429       const std::string& field_name,
430       std::vector<std::unique_ptr<int>> StructType::*field) {
431     fields_.push_back(
432         MakeUnique<internal::FieldConverter<StructType,
433                                             std::vector<std::unique_ptr<int>>>>(
434             field_name, field, new internal::RepeatedValueConverter<int>));
435   }
436 
RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::string>> StructType::* field)437   void RegisterRepeatedString(
438       const std::string& field_name,
439       std::vector<std::unique_ptr<std::string>> StructType::*field) {
440     fields_.push_back(
441         MakeUnique<internal::FieldConverter<
442             StructType, std::vector<std::unique_ptr<std::string>>>>(
443             field_name, field,
444             new internal::RepeatedValueConverter<std::string>));
445   }
446 
RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<string16>> StructType::* field)447   void RegisterRepeatedString(
448       const std::string& field_name,
449       std::vector<std::unique_ptr<string16>> StructType::*field) {
450     fields_.push_back(MakeUnique<internal::FieldConverter<
451                           StructType, std::vector<std::unique_ptr<string16>>>>(
452         field_name, field, new internal::RepeatedValueConverter<string16>));
453   }
454 
RegisterRepeatedDouble(const std::string & field_name,std::vector<std::unique_ptr<double>> StructType::* field)455   void RegisterRepeatedDouble(
456       const std::string& field_name,
457       std::vector<std::unique_ptr<double>> StructType::*field) {
458     fields_.push_back(MakeUnique<internal::FieldConverter<
459                           StructType, std::vector<std::unique_ptr<double>>>>(
460         field_name, field, new internal::RepeatedValueConverter<double>));
461   }
462 
RegisterRepeatedBool(const std::string & field_name,std::vector<std::unique_ptr<bool>> StructType::* field)463   void RegisterRepeatedBool(
464       const std::string& field_name,
465       std::vector<std::unique_ptr<bool>> StructType::*field) {
466     fields_.push_back(MakeUnique<internal::FieldConverter<
467                           StructType, std::vector<std::unique_ptr<bool>>>>(
468         field_name, field, new internal::RepeatedValueConverter<bool>));
469   }
470 
471   template <class NestedType>
RegisterRepeatedCustomValue(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field,bool (* convert_func)(const base::Value *,NestedType *))472   void RegisterRepeatedCustomValue(
473       const std::string& field_name,
474       std::vector<std::unique_ptr<NestedType>> StructType::*field,
475       bool (*convert_func)(const base::Value*, NestedType*)) {
476     fields_.push_back(
477         MakeUnique<internal::FieldConverter<
478             StructType, std::vector<std::unique_ptr<NestedType>>>>(
479             field_name, field,
480             new internal::RepeatedCustomValueConverter<NestedType>(
481                 convert_func)));
482   }
483 
484   template <class NestedType>
RegisterRepeatedMessage(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field)485   void RegisterRepeatedMessage(
486       const std::string& field_name,
487       std::vector<std::unique_ptr<NestedType>> StructType::*field) {
488     fields_.push_back(
489         MakeUnique<internal::FieldConverter<
490             StructType, std::vector<std::unique_ptr<NestedType>>>>(
491             field_name, field,
492             new internal::RepeatedMessageConverter<NestedType>));
493   }
494 
Convert(const base::Value & value,StructType * output)495   bool Convert(const base::Value& value, StructType* output) const {
496     const DictionaryValue* dictionary_value = NULL;
497     if (!value.GetAsDictionary(&dictionary_value))
498       return false;
499 
500     for (size_t i = 0; i < fields_.size(); ++i) {
501       const internal::FieldConverterBase<StructType>* field_converter =
502           fields_[i].get();
503       const base::Value* field = NULL;
504       if (dictionary_value->Get(field_converter->field_path(), &field)) {
505         if (!field_converter->ConvertField(*field, output)) {
506           DVLOG(1) << "failure at field " << field_converter->field_path();
507           return false;
508         }
509       }
510     }
511     return true;
512   }
513 
514  private:
515   std::vector<std::unique_ptr<internal::FieldConverterBase<StructType>>>
516       fields_;
517 
518   DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
519 };
520 
521 }  // namespace base
522 
523 #endif  // BASE_JSON_JSON_VALUE_CONVERTER_H_
524