1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_
11 #include "base/base_export.h"
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_piece.h"
19 #include "base/values.h"
21 // JSONValueConverter converts a JSON value into a C++ struct in a
25 // For real examples, you may want to refer to _unittest.cc file.
27 // Assume that you have a struct like this:
31 // static void RegisterJSONConverter(
32 // JSONValueConverter<Message>* converter);
35 // And you want to parse a json data into this struct. First, you
36 // need to declare RegisterJSONConverter() method in your struct.
38 // void Message::RegisterJSONConverter(
39 // JSONValueConverter<Message>* converter) {
40 // converter->RegisterIntField("foo", &Message::foo);
41 // converter->RegisterStringField("bar", &Message::bar);
44 // Then, you just instantiate your JSONValueConverter of your type and call
47 // JSONValueConverter<Message> converter;
48 // converter.Convert(json, &message);
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.
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.
61 // static void RegisterJSONConverter(...) {
63 // converter->RegisterNestedField("foo", &Nested::foo);
67 // For repeated field, we just assume ScopedVector for its container
68 // and you can put RegisterRepeatedInt or some other types. Use
69 // RegisterRepeatedMessage for nested repeated fields.
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 StringPiece to your type.
74 // bool ConvertFunc(const StringPiece& s, YourEnum* result) {
75 // // do something and return true if succeed...
80 // static void RegisterJSONConverter(...) {
82 // converter->RegsiterCustomField<YourEnum>(
83 // "your_enum", &Message::ye, &ConvertFunc);
89 template <typename StructType
>
90 class JSONValueConverter
;
94 template<typename StructType
>
95 class FieldConverterBase
{
97 explicit FieldConverterBase(const std::string
& path
) : field_path_(path
) {}
98 virtual ~FieldConverterBase() {}
99 virtual bool ConvertField(const base::Value
& value
, StructType
* obj
)
101 const std::string
& field_path() const { return field_path_
; }
104 std::string field_path_
;
105 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase
);
108 template <typename FieldType
>
109 class ValueConverter
{
111 virtual ~ValueConverter() {}
112 virtual bool Convert(const base::Value
& value
, FieldType
* field
) const = 0;
115 template <typename StructType
, typename FieldType
>
116 class FieldConverter
: public FieldConverterBase
<StructType
> {
118 explicit FieldConverter(const std::string
& path
,
119 FieldType
StructType::* field
,
120 ValueConverter
<FieldType
>* converter
)
121 : FieldConverterBase
<StructType
>(path
),
122 field_pointer_(field
),
123 value_converter_(converter
) {
126 bool ConvertField(const base::Value
& value
, StructType
* dst
) const override
{
127 return value_converter_
->Convert(value
, &(dst
->*field_pointer_
));
131 FieldType
StructType::* field_pointer_
;
132 scoped_ptr
<ValueConverter
<FieldType
> > value_converter_
;
133 DISALLOW_COPY_AND_ASSIGN(FieldConverter
);
136 template <typename FieldType
>
137 class BasicValueConverter
;
140 class BASE_EXPORT BasicValueConverter
<int> : public ValueConverter
<int> {
142 BasicValueConverter() {}
144 bool Convert(const base::Value
& value
, int* field
) const override
;
147 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
151 class BASE_EXPORT BasicValueConverter
<std::string
>
152 : public ValueConverter
<std::string
> {
154 BasicValueConverter() {}
156 bool Convert(const base::Value
& value
, std::string
* field
) const override
;
159 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
163 class BASE_EXPORT BasicValueConverter
<string16
>
164 : public ValueConverter
<string16
> {
166 BasicValueConverter() {}
168 bool Convert(const base::Value
& value
, string16
* field
) const override
;
171 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
175 class BASE_EXPORT BasicValueConverter
<double> : public ValueConverter
<double> {
177 BasicValueConverter() {}
179 bool Convert(const base::Value
& value
, double* field
) const override
;
182 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
186 class BASE_EXPORT BasicValueConverter
<bool> : public ValueConverter
<bool> {
188 BasicValueConverter() {}
190 bool Convert(const base::Value
& value
, bool* field
) const override
;
193 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
196 template <typename FieldType
>
197 class ValueFieldConverter
: public ValueConverter
<FieldType
> {
199 typedef bool(*ConvertFunc
)(const base::Value
* value
, FieldType
* field
);
201 ValueFieldConverter(ConvertFunc convert_func
)
202 : convert_func_(convert_func
) {}
204 bool Convert(const base::Value
& value
, FieldType
* field
) const override
{
205 return convert_func_(&value
, field
);
209 ConvertFunc convert_func_
;
211 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter
);
214 template <typename FieldType
>
215 class CustomFieldConverter
: public ValueConverter
<FieldType
> {
217 typedef bool(*ConvertFunc
)(const StringPiece
& value
, FieldType
* field
);
219 CustomFieldConverter(ConvertFunc convert_func
)
220 : convert_func_(convert_func
) {}
222 bool Convert(const base::Value
& value
, FieldType
* field
) const override
{
223 std::string string_value
;
224 return value
.GetAsString(&string_value
) &&
225 convert_func_(string_value
, field
);
229 ConvertFunc convert_func_
;
231 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter
);
234 template <typename NestedType
>
235 class NestedValueConverter
: public ValueConverter
<NestedType
> {
237 NestedValueConverter() {}
239 bool Convert(const base::Value
& value
, NestedType
* field
) const override
{
240 return converter_
.Convert(value
, field
);
244 JSONValueConverter
<NestedType
> converter_
;
245 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter
);
248 template <typename Element
>
249 class RepeatedValueConverter
: public ValueConverter
<ScopedVector
<Element
> > {
251 RepeatedValueConverter() {}
253 bool Convert(const base::Value
& value
,
254 ScopedVector
<Element
>* field
) const override
{
255 const base::ListValue
* list
= NULL
;
256 if (!value
.GetAsList(&list
)) {
257 // The field is not a list.
261 field
->reserve(list
->GetSize());
262 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
263 const base::Value
* element
= NULL
;
264 if (!list
->Get(i
, &element
))
267 scoped_ptr
<Element
> e(new Element
);
268 if (basic_converter_
.Convert(*element
, e
.get())) {
269 field
->push_back(e
.release());
271 DVLOG(1) << "failure at " << i
<< "-th element";
279 BasicValueConverter
<Element
> basic_converter_
;
280 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter
);
283 template <typename NestedType
>
284 class RepeatedMessageConverter
285 : public ValueConverter
<ScopedVector
<NestedType
> > {
287 RepeatedMessageConverter() {}
289 bool Convert(const base::Value
& value
,
290 ScopedVector
<NestedType
>* field
) const override
{
291 const base::ListValue
* list
= NULL
;
292 if (!value
.GetAsList(&list
))
295 field
->reserve(list
->GetSize());
296 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
297 const base::Value
* element
= NULL
;
298 if (!list
->Get(i
, &element
))
301 scoped_ptr
<NestedType
> nested(new NestedType
);
302 if (converter_
.Convert(*element
, nested
.get())) {
303 field
->push_back(nested
.release());
305 DVLOG(1) << "failure at " << i
<< "-th element";
313 JSONValueConverter
<NestedType
> converter_
;
314 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter
);
317 template <typename NestedType
>
318 class RepeatedCustomValueConverter
319 : public ValueConverter
<ScopedVector
<NestedType
> > {
321 typedef bool(*ConvertFunc
)(const base::Value
* value
, NestedType
* field
);
323 RepeatedCustomValueConverter(ConvertFunc convert_func
)
324 : convert_func_(convert_func
) {}
326 bool Convert(const base::Value
& value
,
327 ScopedVector
<NestedType
>* field
) const override
{
328 const base::ListValue
* list
= NULL
;
329 if (!value
.GetAsList(&list
))
332 field
->reserve(list
->GetSize());
333 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
334 const base::Value
* element
= NULL
;
335 if (!list
->Get(i
, &element
))
338 scoped_ptr
<NestedType
> nested(new NestedType
);
339 if ((*convert_func_
)(element
, nested
.get())) {
340 field
->push_back(nested
.release());
342 DVLOG(1) << "failure at " << i
<< "-th element";
350 ConvertFunc convert_func_
;
351 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter
);
355 } // namespace internal
357 template <class StructType
>
358 class JSONValueConverter
{
360 JSONValueConverter() {
361 StructType::RegisterJSONConverter(this);
364 void RegisterIntField(const std::string
& field_name
,
365 int StructType::* field
) {
366 fields_
.push_back(new internal::FieldConverter
<StructType
, int>(
367 field_name
, field
, new internal::BasicValueConverter
<int>));
370 void RegisterStringField(const std::string
& field_name
,
371 std::string
StructType::* field
) {
372 fields_
.push_back(new internal::FieldConverter
<StructType
, std::string
>(
373 field_name
, field
, new internal::BasicValueConverter
<std::string
>));
376 void RegisterStringField(const std::string
& field_name
,
377 string16
StructType::* field
) {
378 fields_
.push_back(new internal::FieldConverter
<StructType
, string16
>(
379 field_name
, field
, new internal::BasicValueConverter
<string16
>));
382 void RegisterBoolField(const std::string
& field_name
,
383 bool StructType::* field
) {
384 fields_
.push_back(new internal::FieldConverter
<StructType
, bool>(
385 field_name
, field
, new internal::BasicValueConverter
<bool>));
388 void RegisterDoubleField(const std::string
& field_name
,
389 double StructType::* field
) {
390 fields_
.push_back(new internal::FieldConverter
<StructType
, double>(
391 field_name
, field
, new internal::BasicValueConverter
<double>));
394 template <class NestedType
>
395 void RegisterNestedField(
396 const std::string
& field_name
, NestedType
StructType::* field
) {
397 fields_
.push_back(new internal::FieldConverter
<StructType
, NestedType
>(
400 new internal::NestedValueConverter
<NestedType
>));
403 template <typename FieldType
>
404 void RegisterCustomField(
405 const std::string
& field_name
,
406 FieldType
StructType::* field
,
407 bool (*convert_func
)(const StringPiece
&, FieldType
*)) {
408 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
411 new internal::CustomFieldConverter
<FieldType
>(convert_func
)));
414 template <typename FieldType
>
415 void RegisterCustomValueField(
416 const std::string
& field_name
,
417 FieldType
StructType::* field
,
418 bool (*convert_func
)(const base::Value
*, FieldType
*)) {
419 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
422 new internal::ValueFieldConverter
<FieldType
>(convert_func
)));
425 void RegisterRepeatedInt(const std::string
& field_name
,
426 ScopedVector
<int> StructType::* field
) {
428 new internal::FieldConverter
<StructType
, ScopedVector
<int> >(
429 field_name
, field
, new internal::RepeatedValueConverter
<int>));
432 void RegisterRepeatedString(const std::string
& field_name
,
433 ScopedVector
<std::string
> StructType::* field
) {
435 new internal::FieldConverter
<StructType
, ScopedVector
<std::string
> >(
438 new internal::RepeatedValueConverter
<std::string
>));
441 void RegisterRepeatedString(const std::string
& field_name
,
442 ScopedVector
<string16
> StructType::* field
) {
444 new internal::FieldConverter
<StructType
, ScopedVector
<string16
> >(
447 new internal::RepeatedValueConverter
<string16
>));
450 void RegisterRepeatedDouble(const std::string
& field_name
,
451 ScopedVector
<double> StructType::* field
) {
453 new internal::FieldConverter
<StructType
, ScopedVector
<double> >(
454 field_name
, field
, new internal::RepeatedValueConverter
<double>));
457 void RegisterRepeatedBool(const std::string
& field_name
,
458 ScopedVector
<bool> StructType::* field
) {
460 new internal::FieldConverter
<StructType
, ScopedVector
<bool> >(
461 field_name
, field
, new internal::RepeatedValueConverter
<bool>));
464 template <class NestedType
>
465 void RegisterRepeatedCustomValue(
466 const std::string
& field_name
,
467 ScopedVector
<NestedType
> StructType::* field
,
468 bool (*convert_func
)(const base::Value
*, NestedType
*)) {
470 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
473 new internal::RepeatedCustomValueConverter
<NestedType
>(
477 template <class NestedType
>
478 void RegisterRepeatedMessage(const std::string
& field_name
,
479 ScopedVector
<NestedType
> StructType::* field
) {
481 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
484 new internal::RepeatedMessageConverter
<NestedType
>));
487 bool Convert(const base::Value
& value
, StructType
* output
) const {
488 const DictionaryValue
* dictionary_value
= NULL
;
489 if (!value
.GetAsDictionary(&dictionary_value
))
492 for(size_t i
= 0; i
< fields_
.size(); ++i
) {
493 const internal::FieldConverterBase
<StructType
>* field_converter
=
495 const base::Value
* field
= NULL
;
496 if (dictionary_value
->Get(field_converter
->field_path(), &field
)) {
497 if (!field_converter
->ConvertField(*field
, output
)) {
498 DVLOG(1) << "failure at field " << field_converter
->field_path();
507 ScopedVector
<internal::FieldConverterBase
<StructType
> > fields_
;
509 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter
);
514 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_