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 <string> 11 #include <vector> 12 13 #include "base/base_export.h" 14 #include "base/logging.h" 15 #include "base/macros.h" 16 #include "base/memory/scoped_ptr.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 scoped_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 scoped_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 scoped_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 scoped_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