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
86namespace base {
87
88template <typename StructType>
89class JSONValueConverter;
90
91namespace internal {
92
93template<typename StructType>
94class FieldConverterBase {
95 public:
96  explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
97  virtual ~FieldConverterBase() {}
98  virtual bool ConvertField(const base::Value& value, StructType* obj)
99      const = 0;
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
107template <typename FieldType>
108class ValueConverter {
109 public:
110  virtual ~ValueConverter() {}
111  virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
112};
113
114template <typename StructType, typename FieldType>
115class FieldConverter : public FieldConverterBase<StructType> {
116 public:
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
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
136template <typename FieldType>
137class BasicValueConverter;
138
139template <>
140class BasicValueConverter<int> : public ValueConverter<int> {
141 public:
142  BasicValueConverter() {}
143
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
152template <>
153class BasicValueConverter<std::string> : public ValueConverter<std::string> {
154 public:
155  BasicValueConverter() {}
156
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
166template <>
167class BasicValueConverter<string16> : public ValueConverter<string16> {
168 public:
169  BasicValueConverter() {}
170
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
180template <>
181class BasicValueConverter<double> : public ValueConverter<double> {
182 public:
183  BasicValueConverter() {}
184
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
193template <>
194class BasicValueConverter<bool> : public ValueConverter<bool> {
195 public:
196  BasicValueConverter() {}
197
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
206template <typename FieldType>
207class ValueFieldConverter : public ValueConverter<FieldType> {
208 public:
209  typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
210
211  ValueFieldConverter(ConvertFunc convert_func)
212      : convert_func_(convert_func) {}
213
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
225template <typename FieldType>
226class CustomFieldConverter : public ValueConverter<FieldType> {
227 public:
228  typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
229
230  CustomFieldConverter(ConvertFunc convert_func)
231      : convert_func_(convert_func) {}
232
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
246template <typename NestedType>
247class NestedValueConverter : public ValueConverter<NestedType> {
248 public:
249  NestedValueConverter() {}
250
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
261template <typename Element>
262class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
263 public:
264  RepeatedValueConverter() {}
265
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
296template <typename NestedType>
297class RepeatedMessageConverter
298    : public ValueConverter<ScopedVector<NestedType> > {
299 public:
300  RepeatedMessageConverter() {}
301
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
330template <typename NestedType>
331class RepeatedCustomValueConverter
332    : public ValueConverter<ScopedVector<NestedType> > {
333 public:
334  typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
335
336  RepeatedCustomValueConverter(ConvertFunc convert_func)
337      : convert_func_(convert_func) {}
338
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
370template <class StructType>
371class JSONValueConverter {
372 public:
373  JSONValueConverter() {
374    StructType::RegisterJSONConverter(this);
375  }
376
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
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
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
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
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>
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>
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>
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
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
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
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
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
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>
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>
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
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