• 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/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