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