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/logging.h" 18 #include "base/memory/ptr_util.h" 19 #include "base/values.h" 20 21 // JSONValueConverter converts a JSON value into a C++ struct in a 22 // lightweight way. 23 // 24 // Usage: 25 // For real examples, you may want to refer to _unittest.cc file. 26 // 27 // Assume that you have a struct like this: 28 // struct Message { 29 // int foo; 30 // std::string bar; 31 // static void RegisterJSONConverter( 32 // JSONValueConverter<Message>* converter); 33 // }; 34 // 35 // And you want to parse a json data into this struct. First, you 36 // need to declare RegisterJSONConverter() method in your struct. 37 // // static 38 // void Message::RegisterJSONConverter( 39 // JSONValueConverter<Message>* converter) { 40 // converter->RegisterIntField("foo", &Message::foo); 41 // converter->RegisterStringField("bar", &Message::bar); 42 // } 43 // 44 // Then, you just instantiate your JSONValueConverter of your type and call 45 // Convert() method. 46 // Message message; 47 // JSONValueConverter<Message> converter; 48 // converter.Convert(json, &message); 49 // 50 // Convert() returns false when it fails. Here "fail" means that the value is 51 // structurally different from expected, such like a string value appears 52 // for an int field. Do not report failures for missing fields. 53 // Also note that Convert() will modify the passed |message| even when it 54 // fails for performance reason. 55 // 56 // For nested field, the internal message also has to implement the registration 57 // method. Then, just use RegisterNestedField() from the containing struct's 58 // RegisterJSONConverter method. 59 // struct Nested { 60 // Message foo; 61 // static void RegisterJSONConverter(...) { 62 // ... 63 // converter->RegisterNestedField("foo", &Nested::foo); 64 // } 65 // }; 66 // 67 // For repeated field, we just assume std::vector<std::unique_ptr<ElementType>> 68 // for its container and you can put RegisterRepeatedInt or some other types. 69 // Use RegisterRepeatedMessage for nested repeated fields. 70 // 71 // Sometimes JSON format uses string representations for other types such 72 // like enum, timestamp, or URL. You can use RegisterCustomField method 73 // and specify a function to convert a std::string_view to your type. 74 // bool ConvertFunc(std::string_view s, YourEnum* result) { 75 // // do something and return true if succeed... 76 // } 77 // struct Message { 78 // YourEnum ye; 79 // ... 80 // static void RegisterJSONConverter(...) { 81 // ... 82 // converter->RegsiterCustomField<YourEnum>( 83 // "your_enum", &Message::ye, &ConvertFunc); 84 // } 85 // }; 86 87 namespace base { 88 89 template <typename StructType> 90 class JSONValueConverter; 91 92 namespace internal { 93 94 template <typename StructType> 95 class FieldConverterBase { 96 public: FieldConverterBase(const std::string & path)97 explicit FieldConverterBase(const std::string& path) : field_path_(path) {} 98 99 FieldConverterBase(const FieldConverterBase&) = delete; 100 FieldConverterBase& operator=(const FieldConverterBase&) = delete; 101 102 virtual ~FieldConverterBase() = default; 103 virtual bool ConvertField(const base::Value& value, 104 StructType* obj) const = 0; field_path()105 const std::string& field_path() const { return field_path_; } 106 107 private: 108 std::string field_path_; 109 }; 110 111 template <typename FieldType> 112 class ValueConverter { 113 public: 114 virtual ~ValueConverter() = default; 115 virtual bool Convert(const base::Value& value, FieldType* field) const = 0; 116 }; 117 118 template <typename StructType, typename FieldType> 119 class FieldConverter : public FieldConverterBase<StructType> { 120 public: FieldConverter(const std::string & path,FieldType StructType::* field,ValueConverter<FieldType> * converter)121 explicit FieldConverter(const std::string& path, 122 FieldType StructType::*field, 123 ValueConverter<FieldType>* converter) 124 : FieldConverterBase<StructType>(path), 125 field_pointer_(field), 126 value_converter_(converter) {} 127 128 FieldConverter(const FieldConverter&) = delete; 129 FieldConverter& operator=(const FieldConverter&) = delete; 130 ConvertField(const base::Value & value,StructType * dst)131 bool ConvertField(const base::Value& value, StructType* dst) const override { 132 return value_converter_->Convert(value, &(dst->*field_pointer_)); 133 } 134 135 private: 136 FieldType StructType::*field_pointer_; 137 std::unique_ptr<ValueConverter<FieldType>> value_converter_; 138 }; 139 140 template <typename FieldType> 141 class BasicValueConverter; 142 143 template <> 144 class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> { 145 public: 146 BasicValueConverter() = default; 147 148 BasicValueConverter(const BasicValueConverter&) = delete; 149 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 150 151 bool Convert(const base::Value& value, int* field) const override; 152 }; 153 154 template <> 155 class BASE_EXPORT BasicValueConverter<std::string> 156 : public ValueConverter<std::string> { 157 public: 158 BasicValueConverter() = default; 159 160 BasicValueConverter(const BasicValueConverter&) = delete; 161 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 162 163 bool Convert(const base::Value& value, std::string* field) const override; 164 }; 165 166 template <> 167 class BASE_EXPORT BasicValueConverter<std::u16string> 168 : public ValueConverter<std::u16string> { 169 public: 170 BasicValueConverter() = default; 171 172 BasicValueConverter(const BasicValueConverter&) = delete; 173 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 174 175 bool Convert(const base::Value& value, std::u16string* field) const override; 176 }; 177 178 template <> 179 class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> { 180 public: 181 BasicValueConverter() = default; 182 183 BasicValueConverter(const BasicValueConverter&) = delete; 184 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 185 186 bool Convert(const base::Value& value, double* field) const override; 187 }; 188 189 template <> 190 class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> { 191 public: 192 BasicValueConverter() = default; 193 194 BasicValueConverter(const BasicValueConverter&) = delete; 195 BasicValueConverter& operator=(const BasicValueConverter&) = delete; 196 197 bool Convert(const base::Value& value, bool* field) const override; 198 }; 199 200 template <typename FieldType> 201 class ValueFieldConverter : public ValueConverter<FieldType> { 202 public: 203 typedef bool (*ConvertFunc)(const base::Value* value, FieldType* field); 204 ValueFieldConverter(ConvertFunc convert_func)205 explicit ValueFieldConverter(ConvertFunc convert_func) 206 : convert_func_(convert_func) {} 207 208 ValueFieldConverter(const ValueFieldConverter&) = delete; 209 ValueFieldConverter& operator=(const ValueFieldConverter&) = delete; 210 Convert(const base::Value & value,FieldType * field)211 bool Convert(const base::Value& value, FieldType* field) const override { 212 return convert_func_(&value, field); 213 } 214 215 private: 216 ConvertFunc convert_func_; 217 }; 218 219 template <typename FieldType> 220 class CustomFieldConverter : public ValueConverter<FieldType> { 221 public: 222 typedef bool (*ConvertFunc)(std::string_view value, FieldType* field); 223 CustomFieldConverter(ConvertFunc convert_func)224 explicit CustomFieldConverter(ConvertFunc convert_func) 225 : convert_func_(convert_func) {} 226 227 CustomFieldConverter(const CustomFieldConverter&) = delete; 228 CustomFieldConverter& operator=(const CustomFieldConverter&) = delete; 229 Convert(const base::Value & value,FieldType * field)230 bool Convert(const base::Value& value, FieldType* field) const override { 231 return value.is_string() && convert_func_(value.GetString(), field); 232 } 233 234 private: 235 ConvertFunc convert_func_; 236 }; 237 238 template <typename NestedType> 239 class NestedValueConverter : public ValueConverter<NestedType> { 240 public: 241 NestedValueConverter() = default; 242 243 NestedValueConverter(const NestedValueConverter&) = delete; 244 NestedValueConverter& operator=(const NestedValueConverter&) = delete; 245 Convert(const base::Value & value,NestedType * field)246 bool Convert(const base::Value& value, NestedType* field) const override { 247 return converter_.Convert(value, field); 248 } 249 250 private: 251 JSONValueConverter<NestedType> converter_; 252 }; 253 254 template <typename Element> 255 class RepeatedValueConverter 256 : public ValueConverter<std::vector<std::unique_ptr<Element>>> { 257 public: 258 RepeatedValueConverter() = default; 259 260 RepeatedValueConverter(const RepeatedValueConverter&) = delete; 261 RepeatedValueConverter& operator=(const RepeatedValueConverter&) = delete; 262 Convert(const base::Value & value,std::vector<std::unique_ptr<Element>> * field)263 bool Convert(const base::Value& value, 264 std::vector<std::unique_ptr<Element>>* field) const override { 265 const Value::List* list = value.GetIfList(); 266 if (!list) { 267 // The field is not a list. 268 return false; 269 } 270 271 field->reserve(list->size()); 272 size_t i = 0; 273 for (const Value& element : *list) { 274 auto e = std::make_unique<Element>(); 275 if (basic_converter_.Convert(element, e.get())) { 276 field->push_back(std::move(e)); 277 } else { 278 DVLOG(1) << "failure at " << i << "-th element"; 279 return false; 280 } 281 i++; 282 } 283 return true; 284 } 285 286 private: 287 BasicValueConverter<Element> basic_converter_; 288 }; 289 290 template <typename NestedType> 291 class RepeatedMessageConverter 292 : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { 293 public: 294 RepeatedMessageConverter() = default; 295 296 RepeatedMessageConverter(const RepeatedMessageConverter&) = delete; 297 RepeatedMessageConverter& operator=(const RepeatedMessageConverter&) = delete; 298 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)299 bool Convert(const base::Value& value, 300 std::vector<std::unique_ptr<NestedType>>* field) const override { 301 const Value::List* list = value.GetIfList(); 302 if (!list) 303 return false; 304 305 field->reserve(list->size()); 306 size_t i = 0; 307 for (const Value& element : *list) { 308 auto nested = std::make_unique<NestedType>(); 309 if (converter_.Convert(element, nested.get())) { 310 field->push_back(std::move(nested)); 311 } else { 312 DVLOG(1) << "failure at " << i << "-th element"; 313 return false; 314 } 315 i++; 316 } 317 return true; 318 } 319 320 private: 321 JSONValueConverter<NestedType> converter_; 322 }; 323 324 template <typename NestedType> 325 class RepeatedCustomValueConverter 326 : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { 327 public: 328 typedef bool (*ConvertFunc)(const base::Value* value, NestedType* field); 329 RepeatedCustomValueConverter(ConvertFunc convert_func)330 explicit RepeatedCustomValueConverter(ConvertFunc convert_func) 331 : convert_func_(convert_func) {} 332 333 RepeatedCustomValueConverter(const RepeatedCustomValueConverter&) = delete; 334 RepeatedCustomValueConverter& operator=(const RepeatedCustomValueConverter&) = 335 delete; 336 Convert(const base::Value & value,std::vector<std::unique_ptr<NestedType>> * field)337 bool Convert(const base::Value& value, 338 std::vector<std::unique_ptr<NestedType>>* field) const override { 339 const Value::List* list = value.GetIfList(); 340 if (!list) 341 return false; 342 343 field->reserve(list->size()); 344 size_t i = 0; 345 for (const Value& element : *list) { 346 auto nested = std::make_unique<NestedType>(); 347 if ((*convert_func_)(&element, nested.get())) { 348 field->push_back(std::move(nested)); 349 } else { 350 DVLOG(1) << "failure at " << i << "-th element"; 351 return false; 352 } 353 i++; 354 } 355 return true; 356 } 357 358 private: 359 ConvertFunc convert_func_; 360 }; 361 362 } // namespace internal 363 364 template <class StructType> 365 class JSONValueConverter { 366 public: JSONValueConverter()367 JSONValueConverter() { StructType::RegisterJSONConverter(this); } 368 369 JSONValueConverter(const JSONValueConverter&) = delete; 370 JSONValueConverter& operator=(const JSONValueConverter&) = delete; 371 RegisterIntField(const std::string & field_name,int StructType::* field)372 void RegisterIntField(const std::string& field_name, int StructType::*field) { 373 fields_.push_back( 374 std::make_unique<internal::FieldConverter<StructType, int>>( 375 field_name, field, new internal::BasicValueConverter<int>)); 376 } 377 RegisterStringField(const std::string & field_name,std::string StructType::* field)378 void RegisterStringField(const std::string& field_name, 379 std::string StructType::*field) { 380 fields_.push_back( 381 std::make_unique<internal::FieldConverter<StructType, std::string>>( 382 field_name, field, new internal::BasicValueConverter<std::string>)); 383 } 384 RegisterStringField(const std::string & field_name,std::u16string StructType::* field)385 void RegisterStringField(const std::string& field_name, 386 std::u16string StructType::*field) { 387 fields_.push_back( 388 std::make_unique<internal::FieldConverter<StructType, std::u16string>>( 389 field_name, field, 390 new internal::BasicValueConverter<std::u16string>)); 391 } 392 RegisterBoolField(const std::string & field_name,bool StructType::* field)393 void RegisterBoolField(const std::string& field_name, 394 bool StructType::*field) { 395 fields_.push_back( 396 std::make_unique<internal::FieldConverter<StructType, bool>>( 397 field_name, field, new internal::BasicValueConverter<bool>)); 398 } 399 RegisterDoubleField(const std::string & field_name,double StructType::* field)400 void RegisterDoubleField(const std::string& field_name, 401 double StructType::*field) { 402 fields_.push_back( 403 std::make_unique<internal::FieldConverter<StructType, double>>( 404 field_name, field, new internal::BasicValueConverter<double>)); 405 } 406 407 template <class NestedType> RegisterNestedField(const std::string & field_name,NestedType StructType::* field)408 void RegisterNestedField(const std::string& field_name, 409 NestedType StructType::*field) { 410 fields_.push_back( 411 std::make_unique<internal::FieldConverter<StructType, NestedType>>( 412 field_name, field, new internal::NestedValueConverter<NestedType>)); 413 } 414 415 template <typename FieldType> RegisterCustomField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(std::string_view,FieldType *))416 void RegisterCustomField(const std::string& field_name, 417 FieldType StructType::*field, 418 bool (*convert_func)(std::string_view, FieldType*)) { 419 fields_.push_back( 420 std::make_unique<internal::FieldConverter<StructType, FieldType>>( 421 field_name, field, 422 new internal::CustomFieldConverter<FieldType>(convert_func))); 423 } 424 425 template <typename FieldType> RegisterCustomValueField(const std::string & field_name,FieldType StructType::* field,bool (* convert_func)(const base::Value *,FieldType *))426 void RegisterCustomValueField(const std::string& field_name, 427 FieldType StructType::*field, 428 bool (*convert_func)(const base::Value*, 429 FieldType*)) { 430 fields_.push_back( 431 std::make_unique<internal::FieldConverter<StructType, FieldType>>( 432 field_name, field, 433 new internal::ValueFieldConverter<FieldType>(convert_func))); 434 } 435 RegisterRepeatedInt(const std::string & field_name,std::vector<std::unique_ptr<int>> StructType::* field)436 void RegisterRepeatedInt( 437 const std::string& field_name, 438 std::vector<std::unique_ptr<int>> StructType::*field) { 439 fields_.push_back(std::make_unique<internal::FieldConverter< 440 StructType, std::vector<std::unique_ptr<int>>>>( 441 field_name, field, new internal::RepeatedValueConverter<int>)); 442 } 443 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::string>> StructType::* field)444 void RegisterRepeatedString( 445 const std::string& field_name, 446 std::vector<std::unique_ptr<std::string>> StructType::*field) { 447 fields_.push_back( 448 std::make_unique<internal::FieldConverter< 449 StructType, std::vector<std::unique_ptr<std::string>>>>( 450 field_name, field, 451 new internal::RepeatedValueConverter<std::string>)); 452 } 453 RegisterRepeatedString(const std::string & field_name,std::vector<std::unique_ptr<std::u16string>> StructType::* field)454 void RegisterRepeatedString( 455 const std::string& field_name, 456 std::vector<std::unique_ptr<std::u16string>> StructType::*field) { 457 fields_.push_back( 458 std::make_unique<internal::FieldConverter< 459 StructType, std::vector<std::unique_ptr<std::u16string>>>>( 460 field_name, field, 461 new internal::RepeatedValueConverter<std::u16string>)); 462 } 463 RegisterRepeatedDouble(const std::string & field_name,std::vector<std::unique_ptr<double>> StructType::* field)464 void RegisterRepeatedDouble( 465 const std::string& field_name, 466 std::vector<std::unique_ptr<double>> StructType::*field) { 467 fields_.push_back(std::make_unique<internal::FieldConverter< 468 StructType, std::vector<std::unique_ptr<double>>>>( 469 field_name, field, new internal::RepeatedValueConverter<double>)); 470 } 471 RegisterRepeatedBool(const std::string & field_name,std::vector<std::unique_ptr<bool>> StructType::* field)472 void RegisterRepeatedBool( 473 const std::string& field_name, 474 std::vector<std::unique_ptr<bool>> StructType::*field) { 475 fields_.push_back(std::make_unique<internal::FieldConverter< 476 StructType, std::vector<std::unique_ptr<bool>>>>( 477 field_name, field, new internal::RepeatedValueConverter<bool>)); 478 } 479 480 template <class NestedType> RegisterRepeatedCustomValue(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field,bool (* convert_func)(const base::Value *,NestedType *))481 void RegisterRepeatedCustomValue( 482 const std::string& field_name, 483 std::vector<std::unique_ptr<NestedType>> StructType::*field, 484 bool (*convert_func)(const base::Value*, NestedType*)) { 485 fields_.push_back( 486 std::make_unique<internal::FieldConverter< 487 StructType, std::vector<std::unique_ptr<NestedType>>>>( 488 field_name, field, 489 new internal::RepeatedCustomValueConverter<NestedType>( 490 convert_func))); 491 } 492 493 template <class NestedType> RegisterRepeatedMessage(const std::string & field_name,std::vector<std::unique_ptr<NestedType>> StructType::* field)494 void RegisterRepeatedMessage( 495 const std::string& field_name, 496 std::vector<std::unique_ptr<NestedType>> StructType::*field) { 497 fields_.push_back( 498 std::make_unique<internal::FieldConverter< 499 StructType, std::vector<std::unique_ptr<NestedType>>>>( 500 field_name, field, 501 new internal::RepeatedMessageConverter<NestedType>)); 502 } 503 Convert(const base::Value & value,StructType * output)504 bool Convert(const base::Value& value, StructType* output) const { 505 const base::Value::Dict* dict = value.GetIfDict(); 506 if (!dict) 507 return false; 508 509 return Convert(*dict, output); 510 } 511 Convert(const base::Value::Dict & dict,StructType * output)512 bool Convert(const base::Value::Dict& dict, StructType* output) const { 513 for (size_t i = 0; i < fields_.size(); ++i) { 514 const internal::FieldConverterBase<StructType>* field_converter = 515 fields_[i].get(); 516 const base::Value* field = 517 dict.FindByDottedPath(field_converter->field_path()); 518 if (field) { 519 if (!field_converter->ConvertField(*field, output)) { 520 DVLOG(1) << "failure at field " << field_converter->field_path(); 521 return false; 522 } 523 } 524 } 525 return true; 526 } 527 528 private: 529 std::vector<std::unique_ptr<internal::FieldConverterBase<StructType>>> 530 fields_; 531 }; 532 533 } // namespace base 534 535 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ 536