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(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() = default;
    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() = default;
    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() = default;
    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() = default;
    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() = default;
    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() = default;
    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() = default;
    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)(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() = default;
    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() = default;
    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() = default;
    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(
    369         std::make_unique<internal::FieldConverter<StructType, int>>(
    370             field_name, field, new internal::BasicValueConverter<int>));
    371   }
    372 
    373   void RegisterStringField(const std::string& field_name,
    374                            std::string StructType::* field) {
    375     fields_.push_back(
    376         std::make_unique<internal::FieldConverter<StructType, std::string>>(
    377             field_name, field, new internal::BasicValueConverter<std::string>));
    378   }
    379 
    380   void RegisterStringField(const std::string& field_name,
    381                            string16 StructType::* field) {
    382     fields_.push_back(
    383         std::make_unique<internal::FieldConverter<StructType, string16>>(
    384             field_name, field, new internal::BasicValueConverter<string16>));
    385   }
    386 
    387   void RegisterBoolField(const std::string& field_name,
    388                          bool StructType::* field) {
    389     fields_.push_back(
    390         std::make_unique<internal::FieldConverter<StructType, bool>>(
    391             field_name, field, new internal::BasicValueConverter<bool>));
    392   }
    393 
    394   void RegisterDoubleField(const std::string& field_name,
    395                            double StructType::* field) {
    396     fields_.push_back(
    397         std::make_unique<internal::FieldConverter<StructType, double>>(
    398             field_name, field, new internal::BasicValueConverter<double>));
    399   }
    400 
    401   template <class NestedType>
    402   void RegisterNestedField(
    403       const std::string& field_name, NestedType StructType::* field) {
    404     fields_.push_back(
    405         std::make_unique<internal::FieldConverter<StructType, NestedType>>(
    406             field_name, field, new internal::NestedValueConverter<NestedType>));
    407   }
    408 
    409   template <typename FieldType>
    410   void RegisterCustomField(const std::string& field_name,
    411                            FieldType StructType::*field,
    412                            bool (*convert_func)(StringPiece, FieldType*)) {
    413     fields_.push_back(
    414         std::make_unique<internal::FieldConverter<StructType, FieldType>>(
    415             field_name, field,
    416             new internal::CustomFieldConverter<FieldType>(convert_func)));
    417   }
    418 
    419   template <typename FieldType>
    420   void RegisterCustomValueField(
    421       const std::string& field_name,
    422       FieldType StructType::* field,
    423       bool (*convert_func)(const base::Value*, FieldType*)) {
    424     fields_.push_back(
    425         std::make_unique<internal::FieldConverter<StructType, FieldType>>(
    426             field_name, field,
    427             new internal::ValueFieldConverter<FieldType>(convert_func)));
    428   }
    429 
    430   void RegisterRepeatedInt(
    431       const std::string& field_name,
    432       std::vector<std::unique_ptr<int>> StructType::*field) {
    433     fields_.push_back(std::make_unique<internal::FieldConverter<
    434                           StructType, std::vector<std::unique_ptr<int>>>>(
    435         field_name, field, new internal::RepeatedValueConverter<int>));
    436   }
    437 
    438   void RegisterRepeatedString(
    439       const std::string& field_name,
    440       std::vector<std::unique_ptr<std::string>> StructType::*field) {
    441     fields_.push_back(
    442         std::make_unique<internal::FieldConverter<
    443             StructType, std::vector<std::unique_ptr<std::string>>>>(
    444             field_name, field,
    445             new internal::RepeatedValueConverter<std::string>));
    446   }
    447 
    448   void RegisterRepeatedString(
    449       const std::string& field_name,
    450       std::vector<std::unique_ptr<string16>> StructType::*field) {
    451     fields_.push_back(std::make_unique<internal::FieldConverter<
    452                           StructType, std::vector<std::unique_ptr<string16>>>>(
    453         field_name, field, new internal::RepeatedValueConverter<string16>));
    454   }
    455 
    456   void RegisterRepeatedDouble(
    457       const std::string& field_name,
    458       std::vector<std::unique_ptr<double>> StructType::*field) {
    459     fields_.push_back(std::make_unique<internal::FieldConverter<
    460                           StructType, std::vector<std::unique_ptr<double>>>>(
    461         field_name, field, new internal::RepeatedValueConverter<double>));
    462   }
    463 
    464   void RegisterRepeatedBool(
    465       const std::string& field_name,
    466       std::vector<std::unique_ptr<bool>> StructType::*field) {
    467     fields_.push_back(std::make_unique<internal::FieldConverter<
    468                           StructType, std::vector<std::unique_ptr<bool>>>>(
    469         field_name, field, new internal::RepeatedValueConverter<bool>));
    470   }
    471 
    472   template <class NestedType>
    473   void RegisterRepeatedCustomValue(
    474       const std::string& field_name,
    475       std::vector<std::unique_ptr<NestedType>> StructType::*field,
    476       bool (*convert_func)(const base::Value*, NestedType*)) {
    477     fields_.push_back(
    478         std::make_unique<internal::FieldConverter<
    479             StructType, std::vector<std::unique_ptr<NestedType>>>>(
    480             field_name, field,
    481             new internal::RepeatedCustomValueConverter<NestedType>(
    482                 convert_func)));
    483   }
    484 
    485   template <class NestedType>
    486   void RegisterRepeatedMessage(
    487       const std::string& field_name,
    488       std::vector<std::unique_ptr<NestedType>> StructType::*field) {
    489     fields_.push_back(
    490         std::make_unique<internal::FieldConverter<
    491             StructType, std::vector<std::unique_ptr<NestedType>>>>(
    492             field_name, field,
    493             new internal::RepeatedMessageConverter<NestedType>));
    494   }
    495 
    496   bool Convert(const base::Value& value, StructType* output) const {
    497     const DictionaryValue* dictionary_value = NULL;
    498     if (!value.GetAsDictionary(&dictionary_value))
    499       return false;
    500 
    501     for (size_t i = 0; i < fields_.size(); ++i) {
    502       const internal::FieldConverterBase<StructType>* field_converter =
    503           fields_[i].get();
    504       const base::Value* field = NULL;
    505       if (dictionary_value->Get(field_converter->field_path(), &field)) {
    506         if (!field_converter->ConvertField(*field, output)) {
    507           DVLOG(1) << "failure at field " << field_converter->field_path();
    508           return false;
    509         }
    510       }
    511     }
    512     return true;
    513   }
    514 
    515  private:
    516   std::vector<std::unique_ptr<internal::FieldConverterBase<StructType>>>
    517       fields_;
    518 
    519   DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
    520 };
    521 
    522 }  // namespace base
    523 
    524 #endif  // BASE_JSON_JSON_VALUE_CONVERTER_H_
    525