• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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