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: FieldConverterBase(const std::string & path)98 explicit FieldConverterBase(const std::string& path) : field_path_(path) {} ~FieldConverterBase()99 virtual ~FieldConverterBase() {} 100 virtual bool ConvertField(const base::Value& value, StructType* obj) 101 const = 0; field_path()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: ~ValueConverter()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: FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)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 ConvertField(const base::Value & value,StructType * dst)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: BasicValueConverter()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: BasicValueConverter()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: BasicValueConverter()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: BasicValueConverter()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: BasicValueConverter()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 ValueFieldConverter(ConvertFunc convert_func)202 explicit ValueFieldConverter(ConvertFunc convert_func) 203 : convert_func_(convert_func) {} 204 Convert(const base::Value & value,FieldType * field)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 CustomFieldConverter(ConvertFunc convert_func)220 explicit CustomFieldConverter(ConvertFunc convert_func) 221 : convert_func_(convert_func) {} 222 Convert(const base::Value & value,FieldType * field)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: NestedValueConverter()238 NestedValueConverter() {} 239 Convert(const base::Value & value,NestedType * field)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: RepeatedValueConverter()253 RepeatedValueConverter() {} 254 Convert(const base::Value & value,std::vector<std::unique_ptr<Element>> * field)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: RepeatedMessageConverter()289 RepeatedMessageConverter() {} 290 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)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 RepeatedCustomValueConverter(ConvertFunc convert_func)325 explicit RepeatedCustomValueConverter(ConvertFunc convert_func) 326 : convert_func_(convert_func) {} 327 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)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: JSONValueConverter()362 JSONValueConverter() { 363 StructType::RegisterJSONConverter(this); 364 } 365 RegisterIntField(const std::string & field_name,int StructType::* field)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 RegisterStringField(const std::string & field_name,std::string StructType::* field)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 RegisterStringField(const std::string & field_name,string16 StructType::* field)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 RegisterBoolField(const std::string & field_name,bool StructType::* field)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 RegisterDoubleField(const std::string & field_name,double StructType::* field)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> RegisterNestedField(const std::string & field_name,NestedType StructType::* field)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> RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const StringPiece &,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> RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,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 RegisterRepeatedInt(const std::string & field_name,std::vector<std::unique_ptr<int>> StructType::* field)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 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::string>> StructType::* field)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 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<string16>> StructType::* field)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 RegisterRepeatedDouble(const std::string & field_name,std::vector<std::unique_ptr<double>> StructType::* field)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 RegisterRepeatedBool(const std::string & field_name,std::vector<std::unique_ptr<bool>> StructType::* field)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> RegisterRepeatedCustomValue(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field,bool (* convert_func)(const base::Value *,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> RegisterRepeatedMessage(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field)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 Convert(const base::Value & value,StructType * output)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