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