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 virtual bool ConvertField(
127 const base::Value
& value
, StructType
* dst
) const override
{
128 return value_converter_
->Convert(value
, &(dst
->*field_pointer_
));
132 FieldType
StructType::* field_pointer_
;
133 scoped_ptr
<ValueConverter
<FieldType
> > value_converter_
;
134 DISALLOW_COPY_AND_ASSIGN(FieldConverter
);
137 template <typename FieldType
>
138 class BasicValueConverter
;
141 class BASE_EXPORT BasicValueConverter
<int> : public ValueConverter
<int> {
143 BasicValueConverter() {}
145 bool Convert(const base::Value
& value
, int* field
) const override
;
148 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
152 class BASE_EXPORT BasicValueConverter
<std::string
>
153 : public ValueConverter
<std::string
> {
155 BasicValueConverter() {}
157 bool Convert(const base::Value
& value
, std::string
* field
) const override
;
160 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
164 class BASE_EXPORT BasicValueConverter
<string16
>
165 : public ValueConverter
<string16
> {
167 BasicValueConverter() {}
169 bool Convert(const base::Value
& value
, string16
* field
) const override
;
172 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
176 class BASE_EXPORT BasicValueConverter
<double> : public ValueConverter
<double> {
178 BasicValueConverter() {}
180 bool Convert(const base::Value
& value
, double* field
) const override
;
183 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
187 class BASE_EXPORT BasicValueConverter
<bool> : public ValueConverter
<bool> {
189 BasicValueConverter() {}
191 bool Convert(const base::Value
& value
, bool* field
) const override
;
194 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
197 template <typename FieldType
>
198 class ValueFieldConverter
: public ValueConverter
<FieldType
> {
200 typedef bool(*ConvertFunc
)(const base::Value
* value
, FieldType
* field
);
202 ValueFieldConverter(ConvertFunc convert_func
)
203 : convert_func_(convert_func
) {}
205 virtual bool Convert(const base::Value
& value
,
206 FieldType
* field
) const override
{
207 return convert_func_(&value
, field
);
211 ConvertFunc convert_func_
;
213 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter
);
216 template <typename FieldType
>
217 class CustomFieldConverter
: public ValueConverter
<FieldType
> {
219 typedef bool(*ConvertFunc
)(const StringPiece
& value
, FieldType
* field
);
221 CustomFieldConverter(ConvertFunc convert_func
)
222 : convert_func_(convert_func
) {}
224 virtual bool Convert(const base::Value
& value
,
225 FieldType
* field
) const override
{
226 std::string string_value
;
227 return value
.GetAsString(&string_value
) &&
228 convert_func_(string_value
, field
);
232 ConvertFunc convert_func_
;
234 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter
);
237 template <typename NestedType
>
238 class NestedValueConverter
: public ValueConverter
<NestedType
> {
240 NestedValueConverter() {}
242 virtual bool Convert(
243 const base::Value
& value
, NestedType
* field
) const override
{
244 return converter_
.Convert(value
, field
);
248 JSONValueConverter
<NestedType
> converter_
;
249 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter
);
252 template <typename Element
>
253 class RepeatedValueConverter
: public ValueConverter
<ScopedVector
<Element
> > {
255 RepeatedValueConverter() {}
257 virtual bool Convert(
258 const base::Value
& value
, ScopedVector
<Element
>* field
) const override
{
259 const base::ListValue
* list
= NULL
;
260 if (!value
.GetAsList(&list
)) {
261 // The field is not a list.
265 field
->reserve(list
->GetSize());
266 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
267 const base::Value
* element
= NULL
;
268 if (!list
->Get(i
, &element
))
271 scoped_ptr
<Element
> e(new Element
);
272 if (basic_converter_
.Convert(*element
, e
.get())) {
273 field
->push_back(e
.release());
275 DVLOG(1) << "failure at " << i
<< "-th element";
283 BasicValueConverter
<Element
> basic_converter_
;
284 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter
);
287 template <typename NestedType
>
288 class RepeatedMessageConverter
289 : public ValueConverter
<ScopedVector
<NestedType
> > {
291 RepeatedMessageConverter() {}
293 virtual bool Convert(const base::Value
& value
,
294 ScopedVector
<NestedType
>* field
) const override
{
295 const base::ListValue
* list
= NULL
;
296 if (!value
.GetAsList(&list
))
299 field
->reserve(list
->GetSize());
300 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
301 const base::Value
* element
= NULL
;
302 if (!list
->Get(i
, &element
))
305 scoped_ptr
<NestedType
> nested(new NestedType
);
306 if (converter_
.Convert(*element
, nested
.get())) {
307 field
->push_back(nested
.release());
309 DVLOG(1) << "failure at " << i
<< "-th element";
317 JSONValueConverter
<NestedType
> converter_
;
318 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter
);
321 template <typename NestedType
>
322 class RepeatedCustomValueConverter
323 : public ValueConverter
<ScopedVector
<NestedType
> > {
325 typedef bool(*ConvertFunc
)(const base::Value
* value
, NestedType
* field
);
327 RepeatedCustomValueConverter(ConvertFunc convert_func
)
328 : convert_func_(convert_func
) {}
330 virtual bool Convert(const base::Value
& value
,
331 ScopedVector
<NestedType
>* field
) const override
{
332 const base::ListValue
* list
= NULL
;
333 if (!value
.GetAsList(&list
))
336 field
->reserve(list
->GetSize());
337 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
338 const base::Value
* element
= NULL
;
339 if (!list
->Get(i
, &element
))
342 scoped_ptr
<NestedType
> nested(new NestedType
);
343 if ((*convert_func_
)(element
, nested
.get())) {
344 field
->push_back(nested
.release());
346 DVLOG(1) << "failure at " << i
<< "-th element";
354 ConvertFunc convert_func_
;
355 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter
);
359 } // namespace internal
361 template <class StructType
>
362 class JSONValueConverter
{
364 JSONValueConverter() {
365 StructType::RegisterJSONConverter(this);
368 void RegisterIntField(const std::string
& field_name
,
369 int StructType::* field
) {
370 fields_
.push_back(new internal::FieldConverter
<StructType
, int>(
371 field_name
, field
, new internal::BasicValueConverter
<int>));
374 void RegisterStringField(const std::string
& field_name
,
375 std::string
StructType::* field
) {
376 fields_
.push_back(new internal::FieldConverter
<StructType
, std::string
>(
377 field_name
, field
, new internal::BasicValueConverter
<std::string
>));
380 void RegisterStringField(const std::string
& field_name
,
381 string16
StructType::* field
) {
382 fields_
.push_back(new internal::FieldConverter
<StructType
, string16
>(
383 field_name
, field
, new internal::BasicValueConverter
<string16
>));
386 void RegisterBoolField(const std::string
& field_name
,
387 bool StructType::* field
) {
388 fields_
.push_back(new internal::FieldConverter
<StructType
, bool>(
389 field_name
, field
, new internal::BasicValueConverter
<bool>));
392 void RegisterDoubleField(const std::string
& field_name
,
393 double StructType::* field
) {
394 fields_
.push_back(new internal::FieldConverter
<StructType
, double>(
395 field_name
, field
, new internal::BasicValueConverter
<double>));
398 template <class NestedType
>
399 void RegisterNestedField(
400 const std::string
& field_name
, NestedType
StructType::* field
) {
401 fields_
.push_back(new internal::FieldConverter
<StructType
, NestedType
>(
404 new internal::NestedValueConverter
<NestedType
>));
407 template <typename FieldType
>
408 void RegisterCustomField(
409 const std::string
& field_name
,
410 FieldType
StructType::* field
,
411 bool (*convert_func
)(const StringPiece
&, FieldType
*)) {
412 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
415 new internal::CustomFieldConverter
<FieldType
>(convert_func
)));
418 template <typename FieldType
>
419 void RegisterCustomValueField(
420 const std::string
& field_name
,
421 FieldType
StructType::* field
,
422 bool (*convert_func
)(const base::Value
*, FieldType
*)) {
423 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
426 new internal::ValueFieldConverter
<FieldType
>(convert_func
)));
429 void RegisterRepeatedInt(const std::string
& field_name
,
430 ScopedVector
<int> StructType::* field
) {
432 new internal::FieldConverter
<StructType
, ScopedVector
<int> >(
433 field_name
, field
, new internal::RepeatedValueConverter
<int>));
436 void RegisterRepeatedString(const std::string
& field_name
,
437 ScopedVector
<std::string
> StructType::* field
) {
439 new internal::FieldConverter
<StructType
, ScopedVector
<std::string
> >(
442 new internal::RepeatedValueConverter
<std::string
>));
445 void RegisterRepeatedString(const std::string
& field_name
,
446 ScopedVector
<string16
> StructType::* field
) {
448 new internal::FieldConverter
<StructType
, ScopedVector
<string16
> >(
451 new internal::RepeatedValueConverter
<string16
>));
454 void RegisterRepeatedDouble(const std::string
& field_name
,
455 ScopedVector
<double> StructType::* field
) {
457 new internal::FieldConverter
<StructType
, ScopedVector
<double> >(
458 field_name
, field
, new internal::RepeatedValueConverter
<double>));
461 void RegisterRepeatedBool(const std::string
& field_name
,
462 ScopedVector
<bool> StructType::* field
) {
464 new internal::FieldConverter
<StructType
, ScopedVector
<bool> >(
465 field_name
, field
, new internal::RepeatedValueConverter
<bool>));
468 template <class NestedType
>
469 void RegisterRepeatedCustomValue(
470 const std::string
& field_name
,
471 ScopedVector
<NestedType
> StructType::* field
,
472 bool (*convert_func
)(const base::Value
*, NestedType
*)) {
474 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
477 new internal::RepeatedCustomValueConverter
<NestedType
>(
481 template <class NestedType
>
482 void RegisterRepeatedMessage(const std::string
& field_name
,
483 ScopedVector
<NestedType
> StructType::* field
) {
485 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
488 new internal::RepeatedMessageConverter
<NestedType
>));
491 bool Convert(const base::Value
& value
, StructType
* output
) const {
492 const DictionaryValue
* dictionary_value
= NULL
;
493 if (!value
.GetAsDictionary(&dictionary_value
))
496 for(size_t i
= 0; i
< fields_
.size(); ++i
) {
497 const internal::FieldConverterBase
<StructType
>* field_converter
=
499 const base::Value
* field
= NULL
;
500 if (dictionary_value
->Get(field_converter
->field_path(), &field
)) {
501 if (!field_converter
->ConvertField(*field
, output
)) {
502 DVLOG(1) << "failure at field " << field_converter
->field_path();
511 ScopedVector
<internal::FieldConverterBase
<StructType
> > fields_
;
513 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter
);
518 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_