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