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
89namespace base {
90
91template <typename StructType>
92class JSONValueConverter;
93
94namespace internal {
95
96template<typename StructType>
97class FieldConverterBase {
98 public:
99  explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
100  virtual ~FieldConverterBase() {}
101  virtual bool ConvertField(const base::Value& value, StructType* obj)
102      const = 0;
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
110template <typename FieldType>
111class ValueConverter {
112 public:
113  virtual ~ValueConverter() {}
114  virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
115};
116
117template <typename StructType, typename FieldType>
118class FieldConverter : public FieldConverterBase<StructType> {
119 public:
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
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
138template <typename FieldType>
139class BasicValueConverter;
140
141template <>
142class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
143 public:
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
152template <>
153class BASE_EXPORT BasicValueConverter<std::string>
154    : public ValueConverter<std::string> {
155 public:
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
164template <>
165class BASE_EXPORT BasicValueConverter<string16>
166    : public ValueConverter<string16> {
167 public:
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
176template <>
177class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
178 public:
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
187template <>
188class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
189 public:
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
198template <typename FieldType>
199class ValueFieldConverter : public ValueConverter<FieldType> {
200 public:
201  typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
202
203  ValueFieldConverter(ConvertFunc convert_func)
204      : convert_func_(convert_func) {}
205
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
216template <typename FieldType>
217class CustomFieldConverter : public ValueConverter<FieldType> {
218 public:
219  typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
220
221  CustomFieldConverter(ConvertFunc convert_func)
222      : convert_func_(convert_func) {}
223
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
236template <typename NestedType>
237class NestedValueConverter : public ValueConverter<NestedType> {
238 public:
239  NestedValueConverter() {}
240
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
250template <typename Element>
251class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
252 public:
253  RepeatedValueConverter() {}
254
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
285template <typename NestedType>
286class RepeatedMessageConverter
287    : public ValueConverter<ScopedVector<NestedType> > {
288 public:
289  RepeatedMessageConverter() {}
290
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
319template <typename NestedType>
320class RepeatedCustomValueConverter
321    : public ValueConverter<ScopedVector<NestedType> > {
322 public:
323  typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
324
325  RepeatedCustomValueConverter(ConvertFunc convert_func)
326      : convert_func_(convert_func) {}
327
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
359template <class StructType>
360class JSONValueConverter {
361 public:
362  JSONValueConverter() {
363    StructType::RegisterJSONConverter(this);
364  }
365
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
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
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
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
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>
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>
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>
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
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
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
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
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
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>
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>
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
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