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/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:
     98   explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
     99   virtual ~FieldConverterBase() {}
    100   virtual bool ConvertField(const base::Value& value, StructType* obj)
    101       const = 0;
    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:
    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:
    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 
    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:
    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:
    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:
    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:
    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:
    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 
    202   explicit ValueFieldConverter(ConvertFunc convert_func)
    203       : convert_func_(convert_func) {}
    204 
    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 
    220   explicit CustomFieldConverter(ConvertFunc convert_func)
    221       : convert_func_(convert_func) {}
    222 
    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:
    238   NestedValueConverter() {}
    239 
    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:
    253   RepeatedValueConverter() {}
    254 
    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:
    289   RepeatedMessageConverter() {}
    290 
    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 
    325   explicit RepeatedCustomValueConverter(ConvertFunc convert_func)
    326       : convert_func_(convert_func) {}
    327 
    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:
    362   JSONValueConverter() {
    363     StructType::RegisterJSONConverter(this);
    364   }
    365 
    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 
    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 
    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 
    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 
    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>
    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>
    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>
    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 
    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 
    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 
    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 
    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 
    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>
    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>
    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 
    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