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