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