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_