Home | History | Annotate | Download | only in json
      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/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:
     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 
    110 template <typename FieldType>
    111 class ValueConverter {
    112  public:
    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:
    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   std::unique_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:
    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:
    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:
    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:
    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:
    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 
    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 
    216 template <typename FieldType>
    217 class 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 
    236 template <typename NestedType>
    237 class 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 
    250 template <typename Element>
    251 class 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       std::unique_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:
    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       std::unique_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 
    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       std::unique_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:
    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