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 <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 
     86 namespace base {
     87 
     88 template <typename StructType>
     89 class JSONValueConverter;
     90 
     91 namespace internal {
     92 
     93 template<typename StructType>
     94 class 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 
    107 template <typename FieldType>
    108 class ValueConverter {
    109  public:
    110   virtual ~ValueConverter() {}
    111   virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
    112 };
    113 
    114 template <typename StructType, typename FieldType>
    115 class 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 
    136 template <typename FieldType>
    137 class BasicValueConverter;
    138 
    139 template <>
    140 class 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 
    152 template <>
    153 class 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 
    166 template <>
    167 class 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 
    180 template <>
    181 class 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 
    193 template <>
    194 class 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 
    206 template <typename FieldType>
    207 class 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 
    225 template <typename FieldType>
    226 class 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 
    246 template <typename NestedType>
    247 class 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 
    261 template <typename Element>
    262 class 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 
    296 template <typename NestedType>
    297 class 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 
    330 template <typename NestedType>
    331 class 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 
    370 template <class StructType>
    371 class 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