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