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