1 // Copyright 2012 The Chromium Authors 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 <string_view> 13 #include <utility> 14 #include <vector> 15 16 #include "base/base_export.h" 17 #include "base/compiler_specific.h" 18 #include "base/logging.h" 19 #include "base/memory/ptr_util.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 std::string_view to your type. 75 // bool ConvertFunc(std::string_view 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) {} 99 100 FieldConverterBase(const FieldConverterBase&) = delete; 101 FieldConverterBase& operator=(const FieldConverterBase&) = delete; 102 103 virtual ~FieldConverterBase() = default; 104 virtual bool ConvertField(const base::Value& value, 105 StructType* obj) const = 0; field_path()106 const std::string& field_path() const LIFETIME_BOUND { return field_path_; } 107 108 private: 109 std::string field_path_; 110 }; 111 112 template <typename FieldType> 113 class ValueConverter { 114 public: 115 virtual ~ValueConverter() = default; 116 virtual bool Convert(const base::Value& value, FieldType* field) const = 0; 117 }; 118 119 template <typename StructType, typename FieldType> 120 class FieldConverter : public FieldConverterBase<StructType> { 121 public: FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)122 explicit FieldConverter(const std::string& path, 123 FieldType StructType::*field, 124 ValueConverter<FieldType>* converter) 125 : FieldConverterBase<StructType>(path), 126 field_pointer_(field), 127 value_converter_(converter) {} 128 129 FieldConverter(const FieldConverter&) = delete; 130 FieldConverter& operator=(const FieldConverter&) = delete; 131 ConvertField(const base::Value & value,StructType * dst)132 bool ConvertField(const base::Value& value, StructType* dst) const override { 133 return value_converter_->Convert(value, &(dst->*field_pointer_)); 134 } 135 136 private: 137 FieldType StructType::*field_pointer_; 138 std::unique_ptr<ValueConverter<FieldType>> value_converter_; 139 }; 140 141 template <typename FieldType> 142 class BasicValueConverter; 143 144 template <> 145 class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> { 146 public: 147 BasicValueConverter() = default; 148 149 BasicValueConverter(const BasicValueConverter&) = delete; 150 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 151 152 bool Convert(const base::Value& value, int* field) const override; 153 }; 154 155 template <> 156 class BASE_EXPORT BasicValueConverter<std::string> 157 : public ValueConverter<std::string> { 158 public: 159 BasicValueConverter() = default; 160 161 BasicValueConverter(const BasicValueConverter&) = delete; 162 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 163 164 bool Convert(const base::Value& value, std::string* field) const override; 165 }; 166 167 template <> 168 class BASE_EXPORT BasicValueConverter<std::u16string> 169 : public ValueConverter<std::u16string> { 170 public: 171 BasicValueConverter() = default; 172 173 BasicValueConverter(const BasicValueConverter&) = delete; 174 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 175 176 bool Convert(const base::Value& value, std::u16string* field) const override; 177 }; 178 179 template <> 180 class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> { 181 public: 182 BasicValueConverter() = default; 183 184 BasicValueConverter(const BasicValueConverter&) = delete; 185 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 186 187 bool Convert(const base::Value& value, double* field) const override; 188 }; 189 190 template <> 191 class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> { 192 public: 193 BasicValueConverter() = default; 194 195 BasicValueConverter(const BasicValueConverter&) = delete; 196 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 197 198 bool Convert(const base::Value& value, bool* field) const override; 199 }; 200 201 template <typename FieldType> 202 class ValueFieldConverter : public ValueConverter<FieldType> { 203 public: 204 typedef bool (*ConvertFunc)(const base::Value* value, FieldType* field); 205 ValueFieldConverter(ConvertFunc convert_func)206 explicit ValueFieldConverter(ConvertFunc convert_func) 207 : convert_func_(convert_func) {} 208 209 ValueFieldConverter(const ValueFieldConverter&) = delete; 210 ValueFieldConverter& operator=(const ValueFieldConverter&) = delete; 211 Convert(const base::Value & value,FieldType * field)212 bool Convert(const base::Value& value, FieldType* field) const override { 213 return convert_func_(&value, field); 214 } 215 216 private: 217 ConvertFunc convert_func_; 218 }; 219 220 template <typename FieldType> 221 class CustomFieldConverter : public ValueConverter<FieldType> { 222 public: 223 typedef bool (*ConvertFunc)(std::string_view value, FieldType* field); 224 CustomFieldConverter(ConvertFunc convert_func)225 explicit CustomFieldConverter(ConvertFunc convert_func) 226 : convert_func_(convert_func) {} 227 228 CustomFieldConverter(const CustomFieldConverter&) = delete; 229 CustomFieldConverter& operator=(const CustomFieldConverter&) = delete; 230 Convert(const base::Value & value,FieldType * field)231 bool Convert(const base::Value& value, FieldType* field) const override { 232 return value.is_string() && convert_func_(value.GetString(), field); 233 } 234 235 private: 236 ConvertFunc convert_func_; 237 }; 238 239 template <typename NestedType> 240 class NestedValueConverter : public ValueConverter<NestedType> { 241 public: 242 NestedValueConverter() = default; 243 244 NestedValueConverter(const NestedValueConverter&) = delete; 245 NestedValueConverter& operator=(const NestedValueConverter&) = delete; 246 Convert(const base::Value & value,NestedType * field)247 bool Convert(const base::Value& value, NestedType* field) const override { 248 return converter_.Convert(value, field); 249 } 250 251 private: 252 JSONValueConverter<NestedType> converter_; 253 }; 254 255 template <typename Element> 256 class RepeatedValueConverter 257 : public ValueConverter<std::vector<std::unique_ptr<Element>>> { 258 public: 259 RepeatedValueConverter() = default; 260 261 RepeatedValueConverter(const RepeatedValueConverter&) = delete; 262 RepeatedValueConverter& operator=(const RepeatedValueConverter&) = delete; 263 Convert(const base::Value & value,std::vector<std::unique_ptr<Element>> * field)264 bool Convert(const base::Value& value, 265 std::vector<std::unique_ptr<Element>>* field) const override { 266 const Value::List* list = value.GetIfList(); 267 if (!list) { 268 // The field is not a list. 269 return false; 270 } 271 272 field->reserve(list->size()); 273 size_t i = 0; 274 for (const Value& element : *list) { 275 auto e = std::make_unique<Element>(); 276 if (basic_converter_.Convert(element, e.get())) { 277 field->push_back(std::move(e)); 278 } else { 279 DVLOG(1) << "failure at " << i << "-th element"; 280 return false; 281 } 282 i++; 283 } 284 return true; 285 } 286 287 private: 288 BasicValueConverter<Element> basic_converter_; 289 }; 290 291 template <typename NestedType> 292 class RepeatedMessageConverter 293 : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { 294 public: 295 RepeatedMessageConverter() = default; 296 297 RepeatedMessageConverter(const RepeatedMessageConverter&) = delete; 298 RepeatedMessageConverter& operator=(const RepeatedMessageConverter&) = delete; 299 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)300 bool Convert(const base::Value& value, 301 std::vector<std::unique_ptr<NestedType>>* field) const override { 302 const Value::List* list = value.GetIfList(); 303 if (!list) 304 return false; 305 306 field->reserve(list->size()); 307 size_t i = 0; 308 for (const Value& element : *list) { 309 auto nested = std::make_unique<NestedType>(); 310 if (converter_.Convert(element, nested.get())) { 311 field->push_back(std::move(nested)); 312 } else { 313 DVLOG(1) << "failure at " << i << "-th element"; 314 return false; 315 } 316 i++; 317 } 318 return true; 319 } 320 321 private: 322 JSONValueConverter<NestedType> converter_; 323 }; 324 325 template <typename NestedType> 326 class RepeatedCustomValueConverter 327 : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { 328 public: 329 typedef bool (*ConvertFunc)(const base::Value* value, NestedType* field); 330 RepeatedCustomValueConverter(ConvertFunc convert_func)331 explicit RepeatedCustomValueConverter(ConvertFunc convert_func) 332 : convert_func_(convert_func) {} 333 334 RepeatedCustomValueConverter(const RepeatedCustomValueConverter&) = delete; 335 RepeatedCustomValueConverter& operator=(const RepeatedCustomValueConverter&) = 336 delete; 337 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)338 bool Convert(const base::Value& value, 339 std::vector<std::unique_ptr<NestedType>>* field) const override { 340 const Value::List* list = value.GetIfList(); 341 if (!list) 342 return false; 343 344 field->reserve(list->size()); 345 size_t i = 0; 346 for (const Value& element : *list) { 347 auto nested = std::make_unique<NestedType>(); 348 if ((*convert_func_)(&element, nested.get())) { 349 field->push_back(std::move(nested)); 350 } else { 351 DVLOG(1) << "failure at " << i << "-th element"; 352 return false; 353 } 354 i++; 355 } 356 return true; 357 } 358 359 private: 360 ConvertFunc convert_func_; 361 }; 362 363 } // namespace internal 364 365 template <class StructType> 366 class JSONValueConverter { 367 public: JSONValueConverter()368 JSONValueConverter() { StructType::RegisterJSONConverter(this); } 369 370 JSONValueConverter(const JSONValueConverter&) = delete; 371 JSONValueConverter& operator=(const JSONValueConverter&) = delete; 372 RegisterIntField(const std::string & field_name,int StructType::* field)373 void RegisterIntField(const std::string& field_name, int StructType::*field) { 374 fields_.push_back( 375 std::make_unique<internal::FieldConverter<StructType, int>>( 376 field_name, field, new internal::BasicValueConverter<int>)); 377 } 378 RegisterStringField(const std::string & field_name,std::string StructType::* field)379 void RegisterStringField(const std::string& field_name, 380 std::string StructType::*field) { 381 fields_.push_back( 382 std::make_unique<internal::FieldConverter<StructType, std::string>>( 383 field_name, field, new internal::BasicValueConverter<std::string>)); 384 } 385 RegisterStringField(const std::string & field_name,std::u16string StructType::* field)386 void RegisterStringField(const std::string& field_name, 387 std::u16string StructType::*field) { 388 fields_.push_back( 389 std::make_unique<internal::FieldConverter<StructType, std::u16string>>( 390 field_name, field, 391 new internal::BasicValueConverter<std::u16string>)); 392 } 393 RegisterBoolField(const std::string & field_name,bool StructType::* field)394 void RegisterBoolField(const std::string& field_name, 395 bool StructType::*field) { 396 fields_.push_back( 397 std::make_unique<internal::FieldConverter<StructType, bool>>( 398 field_name, field, new internal::BasicValueConverter<bool>)); 399 } 400 RegisterDoubleField(const std::string & field_name,double StructType::* field)401 void RegisterDoubleField(const std::string& field_name, 402 double StructType::*field) { 403 fields_.push_back( 404 std::make_unique<internal::FieldConverter<StructType, double>>( 405 field_name, field, new internal::BasicValueConverter<double>)); 406 } 407 408 template <class NestedType> RegisterNestedField(const std::string & field_name,NestedType StructType::* field)409 void RegisterNestedField(const std::string& field_name, 410 NestedType StructType::*field) { 411 fields_.push_back( 412 std::make_unique<internal::FieldConverter<StructType, NestedType>>( 413 field_name, field, new internal::NestedValueConverter<NestedType>)); 414 } 415 416 template <typename FieldType> RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(std::string_view,FieldType *))417 void RegisterCustomField(const std::string& field_name, 418 FieldType StructType::*field, 419 bool (*convert_func)(std::string_view, FieldType*)) { 420 fields_.push_back( 421 std::make_unique<internal::FieldConverter<StructType, FieldType>>( 422 field_name, field, 423 new internal::CustomFieldConverter<FieldType>(convert_func))); 424 } 425 426 template <typename FieldType> RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,FieldType *))427 void RegisterCustomValueField(const std::string& field_name, 428 FieldType StructType::*field, 429 bool (*convert_func)(const base::Value*, 430 FieldType*)) { 431 fields_.push_back( 432 std::make_unique<internal::FieldConverter<StructType, FieldType>>( 433 field_name, field, 434 new internal::ValueFieldConverter<FieldType>(convert_func))); 435 } 436 RegisterRepeatedInt(const std::string & field_name,std::vector<std::unique_ptr<int>> StructType::* field)437 void RegisterRepeatedInt( 438 const std::string& field_name, 439 std::vector<std::unique_ptr<int>> StructType::*field) { 440 fields_.push_back(std::make_unique<internal::FieldConverter< 441 StructType, std::vector<std::unique_ptr<int>>>>( 442 field_name, field, new internal::RepeatedValueConverter<int>)); 443 } 444 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::string>> StructType::* field)445 void RegisterRepeatedString( 446 const std::string& field_name, 447 std::vector<std::unique_ptr<std::string>> StructType::*field) { 448 fields_.push_back( 449 std::make_unique<internal::FieldConverter< 450 StructType, std::vector<std::unique_ptr<std::string>>>>( 451 field_name, field, 452 new internal::RepeatedValueConverter<std::string>)); 453 } 454 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::u16string>> StructType::* field)455 void RegisterRepeatedString( 456 const std::string& field_name, 457 std::vector<std::unique_ptr<std::u16string>> StructType::*field) { 458 fields_.push_back( 459 std::make_unique<internal::FieldConverter< 460 StructType, std::vector<std::unique_ptr<std::u16string>>>>( 461 field_name, field, 462 new internal::RepeatedValueConverter<std::u16string>)); 463 } 464 RegisterRepeatedDouble(const std::string & field_name,std::vector<std::unique_ptr<double>> StructType::* field)465 void RegisterRepeatedDouble( 466 const std::string& field_name, 467 std::vector<std::unique_ptr<double>> StructType::*field) { 468 fields_.push_back(std::make_unique<internal::FieldConverter< 469 StructType, std::vector<std::unique_ptr<double>>>>( 470 field_name, field, new internal::RepeatedValueConverter<double>)); 471 } 472 RegisterRepeatedBool(const std::string & field_name,std::vector<std::unique_ptr<bool>> StructType::* field)473 void RegisterRepeatedBool( 474 const std::string& field_name, 475 std::vector<std::unique_ptr<bool>> StructType::*field) { 476 fields_.push_back(std::make_unique<internal::FieldConverter< 477 StructType, std::vector<std::unique_ptr<bool>>>>( 478 field_name, field, new internal::RepeatedValueConverter<bool>)); 479 } 480 481 template <class NestedType> RegisterRepeatedCustomValue(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field,bool (* convert_func)(const base::Value *,NestedType *))482 void RegisterRepeatedCustomValue( 483 const std::string& field_name, 484 std::vector<std::unique_ptr<NestedType>> StructType::*field, 485 bool (*convert_func)(const base::Value*, NestedType*)) { 486 fields_.push_back( 487 std::make_unique<internal::FieldConverter< 488 StructType, std::vector<std::unique_ptr<NestedType>>>>( 489 field_name, field, 490 new internal::RepeatedCustomValueConverter<NestedType>( 491 convert_func))); 492 } 493 494 template <class NestedType> RegisterRepeatedMessage(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field)495 void RegisterRepeatedMessage( 496 const std::string& field_name, 497 std::vector<std::unique_ptr<NestedType>> StructType::*field) { 498 fields_.push_back( 499 std::make_unique<internal::FieldConverter< 500 StructType, std::vector<std::unique_ptr<NestedType>>>>( 501 field_name, field, 502 new internal::RepeatedMessageConverter<NestedType>)); 503 } 504 Convert(const base::Value & value,StructType * output)505 bool Convert(const base::Value& value, StructType* output) const { 506 const base::Value::Dict* dict = value.GetIfDict(); 507 if (!dict) 508 return false; 509 510 return Convert(*dict, output); 511 } 512 Convert(const base::Value::Dict & dict,StructType * output)513 bool Convert(const base::Value::Dict& dict, StructType* output) const { 514 for (size_t i = 0; i < fields_.size(); ++i) { 515 const internal::FieldConverterBase<StructType>* field_converter = 516 fields_[i].get(); 517 const base::Value* field = 518 dict.FindByDottedPath(field_converter->field_path()); 519 if (field) { 520 if (!field_converter->ConvertField(*field, output)) { 521 DVLOG(1) << "failure at field " << field_converter->field_path(); 522 return false; 523 } 524 } 525 } 526 return true; 527 } 528 529 private: 530 std::vector<std::unique_ptr<internal::FieldConverterBase<StructType>>> 531 fields_; 532 }; 533 534 } // namespace base 535 536 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ 537