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/basictypes.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_piece.h"
18 #include "base/values.h"
20 // JSONValueConverter converts a JSON value into a C++ struct in a
24 // For real examples, you may want to refer to _unittest.cc file.
26 // Assume that you have a struct like this:
30 // static void RegisterJSONConverter(
31 // JSONValueConverter<Message>* converter);
34 // And you want to parse a json data into this struct. First, you
35 // need to declare RegisterJSONConverter() method in your struct.
37 // void Message::RegisterJSONConverter(
38 // JSONValueConverter<Message>* converter) {
39 // converter->RegisterIntField("foo", &Message::foo);
40 // converter->RegisterStringField("bar", &Message::bar);
43 // Then, you just instantiate your JSONValueConverter of your type and call
46 // JSONValueConverter<Message> converter;
47 // converter.Convert(json, &message);
49 // Convert() returns false when it fails. Here "fail" means that the value is
50 // structurally different from expected, such like a string value appears
51 // for an int field. Do not report failures for missing fields.
52 // Also note that Convert() will modify the passed |message| even when it
53 // fails for performance reason.
55 // For nested field, the internal message also has to implement the registration
56 // method. Then, just use RegisterNestedField() from the containing struct's
57 // RegisterJSONConverter method.
60 // static void RegisterJSONConverter(...) {
62 // converter->RegisterNestedField("foo", &Nested::foo);
66 // For repeated field, we just assume ScopedVector for its container
67 // and you can put RegisterRepeatedInt or some other types. Use
68 // RegisterRepeatedMessage for nested repeated fields.
70 // Sometimes JSON format uses string representations for other types such
71 // like enum, timestamp, or URL. You can use RegisterCustomField method
72 // and specify a function to convert a StringPiece to your type.
73 // bool ConvertFunc(const StringPiece& s, YourEnum* result) {
74 // // do something and return true if succeed...
79 // static void RegisterJSONConverter(...) {
81 // converter->RegsiterCustomField<YourEnum>(
82 // "your_enum", &Message::ye, &ConvertFunc);
88 template <typename StructType
>
89 class JSONValueConverter
;
93 template<typename StructType
>
94 class FieldConverterBase
{
96 explicit FieldConverterBase(const std::string
& path
) : field_path_(path
) {}
97 virtual ~FieldConverterBase() {}
98 virtual bool ConvertField(const base::Value
& value
, StructType
* obj
)
100 const std::string
& field_path() const { return field_path_
; }
103 std::string field_path_
;
104 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase
);
107 template <typename FieldType
>
108 class ValueConverter
{
110 virtual ~ValueConverter() {}
111 virtual bool Convert(const base::Value
& value
, FieldType
* field
) const = 0;
114 template <typename StructType
, typename FieldType
>
115 class FieldConverter
: public FieldConverterBase
<StructType
> {
117 explicit FieldConverter(const std::string
& path
,
118 FieldType
StructType::* field
,
119 ValueConverter
<FieldType
>* converter
)
120 : FieldConverterBase
<StructType
>(path
),
121 field_pointer_(field
),
122 value_converter_(converter
) {
125 virtual bool ConvertField(
126 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 BasicValueConverter
<int> : public ValueConverter
<int> {
142 BasicValueConverter() {}
144 virtual bool Convert(const base::Value
& value
, int* field
) const OVERRIDE
{
145 return value
.GetAsInteger(field
);
149 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
153 class BasicValueConverter
<std::string
> : public ValueConverter
<std::string
> {
155 BasicValueConverter() {}
157 virtual bool Convert(
158 const base::Value
& value
, std::string
* field
) const OVERRIDE
{
159 return value
.GetAsString(field
);
163 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
167 class BasicValueConverter
<string16
> : public ValueConverter
<string16
> {
169 BasicValueConverter() {}
171 virtual bool Convert(
172 const base::Value
& value
, string16
* field
) const OVERRIDE
{
173 return value
.GetAsString(field
);
177 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
181 class BasicValueConverter
<double> : public ValueConverter
<double> {
183 BasicValueConverter() {}
185 virtual bool Convert(const base::Value
& value
, double* field
) const OVERRIDE
{
186 return value
.GetAsDouble(field
);
190 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
194 class BasicValueConverter
<bool> : public ValueConverter
<bool> {
196 BasicValueConverter() {}
198 virtual bool Convert(const base::Value
& value
, bool* field
) const OVERRIDE
{
199 return value
.GetAsBoolean(field
);
203 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter
);
206 template <typename FieldType
>
207 class ValueFieldConverter
: public ValueConverter
<FieldType
> {
209 typedef bool(*ConvertFunc
)(const base::Value
* value
, FieldType
* field
);
211 ValueFieldConverter(ConvertFunc convert_func
)
212 : convert_func_(convert_func
) {}
214 virtual bool Convert(const base::Value
& value
,
215 FieldType
* field
) const OVERRIDE
{
216 return convert_func_(&value
, field
);
220 ConvertFunc convert_func_
;
222 DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter
);
225 template <typename FieldType
>
226 class CustomFieldConverter
: public ValueConverter
<FieldType
> {
228 typedef bool(*ConvertFunc
)(const StringPiece
& value
, FieldType
* field
);
230 CustomFieldConverter(ConvertFunc convert_func
)
231 : convert_func_(convert_func
) {}
233 virtual bool Convert(const base::Value
& value
,
234 FieldType
* field
) const OVERRIDE
{
235 std::string string_value
;
236 return value
.GetAsString(&string_value
) &&
237 convert_func_(string_value
, field
);
241 ConvertFunc convert_func_
;
243 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter
);
246 template <typename NestedType
>
247 class NestedValueConverter
: public ValueConverter
<NestedType
> {
249 NestedValueConverter() {}
251 virtual bool Convert(
252 const base::Value
& value
, NestedType
* field
) const OVERRIDE
{
253 return converter_
.Convert(value
, field
);
257 JSONValueConverter
<NestedType
> converter_
;
258 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter
);
261 template <typename Element
>
262 class RepeatedValueConverter
: public ValueConverter
<ScopedVector
<Element
> > {
264 RepeatedValueConverter() {}
266 virtual bool Convert(
267 const base::Value
& value
, ScopedVector
<Element
>* field
) const OVERRIDE
{
268 const base::ListValue
* list
= NULL
;
269 if (!value
.GetAsList(&list
)) {
270 // The field is not a list.
274 field
->reserve(list
->GetSize());
275 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
276 const base::Value
* element
= NULL
;
277 if (!list
->Get(i
, &element
))
280 scoped_ptr
<Element
> e(new Element
);
281 if (basic_converter_
.Convert(*element
, e
.get())) {
282 field
->push_back(e
.release());
284 DVLOG(1) << "failure at " << i
<< "-th element";
292 BasicValueConverter
<Element
> basic_converter_
;
293 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter
);
296 template <typename NestedType
>
297 class RepeatedMessageConverter
298 : public ValueConverter
<ScopedVector
<NestedType
> > {
300 RepeatedMessageConverter() {}
302 virtual bool Convert(const base::Value
& value
,
303 ScopedVector
<NestedType
>* field
) const OVERRIDE
{
304 const base::ListValue
* list
= NULL
;
305 if (!value
.GetAsList(&list
))
308 field
->reserve(list
->GetSize());
309 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
310 const base::Value
* element
= NULL
;
311 if (!list
->Get(i
, &element
))
314 scoped_ptr
<NestedType
> nested(new NestedType
);
315 if (converter_
.Convert(*element
, nested
.get())) {
316 field
->push_back(nested
.release());
318 DVLOG(1) << "failure at " << i
<< "-th element";
326 JSONValueConverter
<NestedType
> converter_
;
327 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter
);
330 template <typename NestedType
>
331 class RepeatedCustomValueConverter
332 : public ValueConverter
<ScopedVector
<NestedType
> > {
334 typedef bool(*ConvertFunc
)(const base::Value
* value
, NestedType
* field
);
336 RepeatedCustomValueConverter(ConvertFunc convert_func
)
337 : convert_func_(convert_func
) {}
339 virtual bool Convert(const base::Value
& value
,
340 ScopedVector
<NestedType
>* field
) const OVERRIDE
{
341 const base::ListValue
* list
= NULL
;
342 if (!value
.GetAsList(&list
))
345 field
->reserve(list
->GetSize());
346 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
347 const base::Value
* element
= NULL
;
348 if (!list
->Get(i
, &element
))
351 scoped_ptr
<NestedType
> nested(new NestedType
);
352 if ((*convert_func_
)(element
, nested
.get())) {
353 field
->push_back(nested
.release());
355 DVLOG(1) << "failure at " << i
<< "-th element";
363 ConvertFunc convert_func_
;
364 DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter
);
368 } // namespace internal
370 template <class StructType
>
371 class JSONValueConverter
{
373 JSONValueConverter() {
374 StructType::RegisterJSONConverter(this);
377 void RegisterIntField(const std::string
& field_name
,
378 int StructType::* field
) {
379 fields_
.push_back(new internal::FieldConverter
<StructType
, int>(
380 field_name
, field
, new internal::BasicValueConverter
<int>));
383 void RegisterStringField(const std::string
& field_name
,
384 std::string
StructType::* field
) {
385 fields_
.push_back(new internal::FieldConverter
<StructType
, std::string
>(
386 field_name
, field
, new internal::BasicValueConverter
<std::string
>));
389 void RegisterStringField(const std::string
& field_name
,
390 string16
StructType::* field
) {
391 fields_
.push_back(new internal::FieldConverter
<StructType
, string16
>(
392 field_name
, field
, new internal::BasicValueConverter
<string16
>));
395 void RegisterBoolField(const std::string
& field_name
,
396 bool StructType::* field
) {
397 fields_
.push_back(new internal::FieldConverter
<StructType
, bool>(
398 field_name
, field
, new internal::BasicValueConverter
<bool>));
401 void RegisterDoubleField(const std::string
& field_name
,
402 double StructType::* field
) {
403 fields_
.push_back(new internal::FieldConverter
<StructType
, double>(
404 field_name
, field
, new internal::BasicValueConverter
<double>));
407 template <class NestedType
>
408 void RegisterNestedField(
409 const std::string
& field_name
, NestedType
StructType::* field
) {
410 fields_
.push_back(new internal::FieldConverter
<StructType
, NestedType
>(
413 new internal::NestedValueConverter
<NestedType
>));
416 template <typename FieldType
>
417 void RegisterCustomField(
418 const std::string
& field_name
,
419 FieldType
StructType::* field
,
420 bool (*convert_func
)(const StringPiece
&, FieldType
*)) {
421 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
424 new internal::CustomFieldConverter
<FieldType
>(convert_func
)));
427 template <typename FieldType
>
428 void RegisterCustomValueField(
429 const std::string
& field_name
,
430 FieldType
StructType::* field
,
431 bool (*convert_func
)(const base::Value
*, FieldType
*)) {
432 fields_
.push_back(new internal::FieldConverter
<StructType
, FieldType
>(
435 new internal::ValueFieldConverter
<FieldType
>(convert_func
)));
438 void RegisterRepeatedInt(const std::string
& field_name
,
439 ScopedVector
<int> StructType::* field
) {
441 new internal::FieldConverter
<StructType
, ScopedVector
<int> >(
442 field_name
, field
, new internal::RepeatedValueConverter
<int>));
445 void RegisterRepeatedString(const std::string
& field_name
,
446 ScopedVector
<std::string
> StructType::* field
) {
448 new internal::FieldConverter
<StructType
, ScopedVector
<std::string
> >(
451 new internal::RepeatedValueConverter
<std::string
>));
454 void RegisterRepeatedString(const std::string
& field_name
,
455 ScopedVector
<string16
> StructType::* field
) {
457 new internal::FieldConverter
<StructType
, ScopedVector
<string16
> >(
460 new internal::RepeatedValueConverter
<string16
>));
463 void RegisterRepeatedDouble(const std::string
& field_name
,
464 ScopedVector
<double> StructType::* field
) {
466 new internal::FieldConverter
<StructType
, ScopedVector
<double> >(
467 field_name
, field
, new internal::RepeatedValueConverter
<double>));
470 void RegisterRepeatedBool(const std::string
& field_name
,
471 ScopedVector
<bool> StructType::* field
) {
473 new internal::FieldConverter
<StructType
, ScopedVector
<bool> >(
474 field_name
, field
, new internal::RepeatedValueConverter
<bool>));
477 template <class NestedType
>
478 void RegisterRepeatedCustomValue(
479 const std::string
& field_name
,
480 ScopedVector
<NestedType
> StructType::* field
,
481 bool (*convert_func
)(const base::Value
*, NestedType
*)) {
483 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
486 new internal::RepeatedCustomValueConverter
<NestedType
>(
490 template <class NestedType
>
491 void RegisterRepeatedMessage(const std::string
& field_name
,
492 ScopedVector
<NestedType
> StructType::* field
) {
494 new internal::FieldConverter
<StructType
, ScopedVector
<NestedType
> >(
497 new internal::RepeatedMessageConverter
<NestedType
>));
500 bool Convert(const base::Value
& value
, StructType
* output
) const {
501 const DictionaryValue
* dictionary_value
= NULL
;
502 if (!value
.GetAsDictionary(&dictionary_value
))
505 for(size_t i
= 0; i
< fields_
.size(); ++i
) {
506 const internal::FieldConverterBase
<StructType
>* field_converter
=
508 const base::Value
* field
= NULL
;
509 if (dictionary_value
->Get(field_converter
->field_path(), &field
)) {
510 if (!field_converter
->ConvertField(*field
, output
)) {
511 DVLOG(1) << "failure at field " << field_converter
->field_path();
520 ScopedVector
<internal::FieldConverterBase
<StructType
> > fields_
;
522 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter
);
527 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_