blob: 0bb131cba39ee6ba95db4be48d5c73eb1d33935f [file] [log] [blame]
[email protected]261c877e2012-01-05 09:46:421// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]193f946b2011-12-22 18:31:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
6#define BASE_JSON_JSON_VALUE_CONVERTER_H_
7#pragma once
8
9#include <string>
10#include <vector>
11
12#include "base/base_export.h"
13#include "base/basictypes.h"
14#include "base/logging.h"
15#include "base/memory/scoped_ptr.h"
[email protected]a9b8e0a2012-01-14 05:36:1216#include "base/memory/scoped_vector.h"
[email protected]193f946b2011-12-22 18:31:4717#include "base/stl_util.h"
[email protected]261c877e2012-01-05 09:46:4218#include "base/string16.h"
[email protected]6009ca92012-01-13 02:18:0219#include "base/string_piece.h"
[email protected]193f946b2011-12-22 18:31:4720#include "base/values.h"
21
22// JSONValueConverter converts a JSON value into a C++ struct in a
23// lightweight way.
24//
25// Usage:
26// For real examples, you may want to refer to _unittest.cc file.
27//
28// Assume that you have a struct like this:
29// struct Message {
30// int foo;
31// std::string bar;
32// static void RegisterJSONConverter(
33// JSONValueConverter<Message>* converter);
34// };
35//
36// And you want to parse a json data into this struct. First, you
37// need to declare RegisterJSONConverter() method in your struct.
38// // static
39// void Message::RegisterJSONConverter(
40// JSONValueConverter<Message>* converter) {
41// converter->RegisterIntField("foo", &Message::foo);
42// converter->RegisterStringField("bar", &Message::bar);
43// }
44//
45// Then, you just instantiate your JSONValueConverter of your type and call
46// Convert() method.
47// Message message;
48// JSONValueConverter<Message> converter;
49// converter.Convert(json, &message);
50//
[email protected]261c877e2012-01-05 09:46:4251// Convert() returns false when it fails. Here "fail" means that the value is
52// structurally different from expected, such like a string value appears
53// for an int field. Do not report failures for missing fields.
54// Also note that Convert() will modify the passed |message| even when it
55// fails for performance reason.
56//
[email protected]193f946b2011-12-22 18:31:4757// For nested field, the internal message also has to implement the registration
58// method. Then, just use RegisterNestedField() from the containing struct's
59// RegisterJSONConverter method.
60// struct Nested {
61// Message foo;
[email protected]261c877e2012-01-05 09:46:4262// static void RegisterJSONConverter(...) {
[email protected]193f946b2011-12-22 18:31:4763// ...
64// converter->RegisterNestedField("foo", &Nested::foo);
65// }
66// };
67//
[email protected]a9b8e0a2012-01-14 05:36:1268// For repeated field, we just assume ScopedVector for its container
[email protected]193f946b2011-12-22 18:31:4769// and you can put RegisterRepeatedInt or some other types. Use
70// RegisterRepeatedMessage for nested repeated fields.
71//
[email protected]6009ca92012-01-13 02:18:0272// Sometimes JSON format uses string representations for other types such
73// like enum, timestamp, or URL. You can use RegisterCustomField method
74// and specify a function to convert a StringPiece to your type.
75// bool ConvertFunc(const StringPiece& s, YourEnum* result) {
76// // do something and return true if succeed...
77// }
78// struct Message {
79// YourEnum ye;
80// ...
81// static void RegisterJSONConverter(...) {
82// ...
83// converter->RegsiterCustomField<YourEnum>(
84// "your_enum", &Message::ye, &ConvertFunc);
85// }
86// };
[email protected]193f946b2011-12-22 18:31:4787
88namespace base {
89
90template <typename StructType>
91class JSONValueConverter;
92
93namespace internal {
94
95class FieldConverterBase {
96 public:
97 BASE_EXPORT explicit FieldConverterBase(const std::string& path);
98 BASE_EXPORT virtual ~FieldConverterBase();
[email protected]261c877e2012-01-05 09:46:4299 virtual bool ConvertField(const base::Value& value, void* obj) const = 0;
[email protected]193f946b2011-12-22 18:31:47100 const std::string& field_path() const { return field_path_; }
101
102 private:
103 std::string field_path_;
104 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
105};
106
107template <typename FieldType>
108class ValueConverter {
109 public:
110 virtual ~ValueConverter() {}
[email protected]261c877e2012-01-05 09:46:42111 virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
[email protected]193f946b2011-12-22 18:31:47112};
113
114template <typename StructType, typename FieldType>
115class FieldConverter : public FieldConverterBase {
116 public:
117 explicit FieldConverter(const std::string& path,
118 FieldType StructType::* field,
119 ValueConverter<FieldType>* converter)
120 : FieldConverterBase(path),
121 field_pointer_(field),
122 value_converter_(converter) {
123 }
124
[email protected]261c877e2012-01-05 09:46:42125 virtual bool ConvertField(
[email protected]193f946b2011-12-22 18:31:47126 const base::Value& value, void* obj) const OVERRIDE {
127 StructType* dst = reinterpret_cast<StructType*>(obj);
[email protected]261c877e2012-01-05 09:46:42128 return value_converter_->Convert(value, &(dst->*field_pointer_));
[email protected]193f946b2011-12-22 18:31:47129 }
130
131 private:
132 FieldType StructType::* field_pointer_;
133 scoped_ptr<ValueConverter<FieldType> > value_converter_;
134 DISALLOW_COPY_AND_ASSIGN(FieldConverter);
135};
136
137template <typename FieldType>
138class BasicValueConverter;
139
140template <>
141class BasicValueConverter<int> : public ValueConverter<int> {
142 public:
143 BasicValueConverter() {}
144
[email protected]261c877e2012-01-05 09:46:42145 virtual bool Convert(const base::Value& value, int* field) const OVERRIDE {
146 return value.GetAsInteger(field);
[email protected]193f946b2011-12-22 18:31:47147 }
148
149 private:
150 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
151};
152
153template <>
154class BasicValueConverter<std::string> : public ValueConverter<std::string> {
155 public:
156 BasicValueConverter() {}
157
[email protected]261c877e2012-01-05 09:46:42158 virtual bool Convert(
[email protected]193f946b2011-12-22 18:31:47159 const base::Value& value, std::string* field) const OVERRIDE {
[email protected]261c877e2012-01-05 09:46:42160 return value.GetAsString(field);
161 }
162
163 private:
164 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
165};
166
167template <>
168class BasicValueConverter<string16> : public ValueConverter<string16> {
169 public:
170 BasicValueConverter() {}
171
172 virtual bool Convert(
173 const base::Value& value, string16* field) const OVERRIDE {
174 return value.GetAsString(field);
[email protected]193f946b2011-12-22 18:31:47175 }
176
177 private:
178 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
179};
180
181template <>
182class BasicValueConverter<double> : public ValueConverter<double> {
183 public:
184 BasicValueConverter() {}
185
[email protected]261c877e2012-01-05 09:46:42186 virtual bool Convert(const base::Value& value, double* field) const OVERRIDE {
187 return value.GetAsDouble(field);
[email protected]193f946b2011-12-22 18:31:47188 }
189
190 private:
191 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
192};
193
194template <>
195class BasicValueConverter<bool> : public ValueConverter<bool> {
196 public:
197 BasicValueConverter() {}
198
[email protected]261c877e2012-01-05 09:46:42199 virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE {
200 return value.GetAsBoolean(field);
[email protected]193f946b2011-12-22 18:31:47201 }
202
203 private:
204 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
205};
206
[email protected]6009ca92012-01-13 02:18:02207template <typename FieldType>
208class CustomFieldConverter : public ValueConverter<FieldType> {
209 public:
210 typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
211
212 CustomFieldConverter(ConvertFunc convert_func)
213 : convert_func_(convert_func) {}
214
215 virtual bool Convert(const base::Value& value,
216 FieldType* field) const OVERRIDE {
217 std::string string_value;
218 return value.GetAsString(&string_value) &&
219 convert_func_(string_value, field);
220 }
221
222 private:
223 ConvertFunc convert_func_;
224
225 DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
226};
227
[email protected]193f946b2011-12-22 18:31:47228template <typename NestedType>
229class NestedValueConverter : public ValueConverter<NestedType> {
230 public:
231 NestedValueConverter() {}
232
[email protected]261c877e2012-01-05 09:46:42233 virtual bool Convert(
[email protected]193f946b2011-12-22 18:31:47234 const base::Value& value, NestedType* field) const OVERRIDE {
[email protected]261c877e2012-01-05 09:46:42235 return converter_.Convert(value, field);
[email protected]193f946b2011-12-22 18:31:47236 }
237
238 private:
239 JSONValueConverter<NestedType> converter_;
240 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
241};
242
243template <typename Element>
[email protected]a9b8e0a2012-01-14 05:36:12244class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
[email protected]193f946b2011-12-22 18:31:47245 public:
246 RepeatedValueConverter() {}
247
[email protected]261c877e2012-01-05 09:46:42248 virtual bool Convert(
[email protected]a9b8e0a2012-01-14 05:36:12249 const base::Value& value, ScopedVector<Element>* field) const OVERRIDE {
[email protected]193f946b2011-12-22 18:31:47250 const base::ListValue* list = NULL;
251 if (!value.GetAsList(&list)) {
252 // The field is not a list.
[email protected]261c877e2012-01-05 09:46:42253 return false;
[email protected]193f946b2011-12-22 18:31:47254 }
255
256 field->reserve(list->GetSize());
257 for (size_t i = 0; i < list->GetSize(); ++i) {
258 base::Value* element = NULL;
259 if (!list->Get(i, &element))
260 continue;
261
[email protected]a9b8e0a2012-01-14 05:36:12262 Element *e = new Element;
263 if (basic_converter_.Convert(*element, e)) {
264 field->push_back(e);
265 } else {
[email protected]261c877e2012-01-05 09:46:42266 DVLOG(1) << "failure at " << i << "-th element";
267 return false;
268 }
[email protected]193f946b2011-12-22 18:31:47269 }
[email protected]261c877e2012-01-05 09:46:42270 return true;
[email protected]193f946b2011-12-22 18:31:47271 }
272
273 private:
274 BasicValueConverter<Element> basic_converter_;
275 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
276};
277
278template <typename NestedType>
279class RepeatedMessageConverter
[email protected]a9b8e0a2012-01-14 05:36:12280 : public ValueConverter<ScopedVector<NestedType> > {
[email protected]193f946b2011-12-22 18:31:47281 public:
282 RepeatedMessageConverter() {}
283
[email protected]a9b8e0a2012-01-14 05:36:12284 virtual bool Convert(const base::Value& value,
285 ScopedVector<NestedType>* field) const OVERRIDE {
[email protected]193f946b2011-12-22 18:31:47286 const base::ListValue* list = NULL;
287 if (!value.GetAsList(&list))
[email protected]261c877e2012-01-05 09:46:42288 return false;
[email protected]193f946b2011-12-22 18:31:47289
290 field->reserve(list->GetSize());
291 for (size_t i = 0; i < list->GetSize(); ++i) {
292 base::Value* element = NULL;
293 if (!list->Get(i, &element))
294 continue;
295
[email protected]a9b8e0a2012-01-14 05:36:12296 NestedType* nested = new NestedType();
297 if (converter_.Convert(*element, nested)) {
298 field->push_back(nested);
299 } else {
[email protected]261c877e2012-01-05 09:46:42300 DVLOG(1) << "failure at " << i << "-th element";
301 return false;
302 }
[email protected]193f946b2011-12-22 18:31:47303 }
[email protected]261c877e2012-01-05 09:46:42304 return true;
[email protected]193f946b2011-12-22 18:31:47305 }
306
307 private:
308 JSONValueConverter<NestedType> converter_;
309 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
310};
311
312} // namespace internal
313
314template <class StructType>
315class JSONValueConverter {
316 public:
317 JSONValueConverter() {
318 StructType::RegisterJSONConverter(this);
319 }
320
[email protected]193f946b2011-12-22 18:31:47321 void RegisterIntField(const std::string& field_name,
322 int StructType::* field) {
323 fields_.push_back(new internal::FieldConverter<StructType, int>(
324 field_name, field, new internal::BasicValueConverter<int>));
325 }
326
327 void RegisterStringField(const std::string& field_name,
[email protected]261c877e2012-01-05 09:46:42328 std::string StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47329 fields_.push_back(new internal::FieldConverter<StructType, std::string>(
330 field_name, field, new internal::BasicValueConverter<std::string>));
331 }
332
[email protected]261c877e2012-01-05 09:46:42333 void RegisterStringField(const std::string& field_name,
334 string16 StructType::* field) {
335 fields_.push_back(new internal::FieldConverter<StructType, string16>(
336 field_name, field, new internal::BasicValueConverter<string16>));
337 }
338
[email protected]193f946b2011-12-22 18:31:47339 void RegisterBoolField(const std::string& field_name,
340 bool StructType::* field) {
341 fields_.push_back(new internal::FieldConverter<StructType, bool>(
342 field_name, field, new internal::BasicValueConverter<bool>));
343 }
344
345 void RegisterDoubleField(const std::string& field_name,
346 double StructType::* field) {
347 fields_.push_back(new internal::FieldConverter<StructType, double>(
348 field_name, field, new internal::BasicValueConverter<double>));
349 }
350
351 template <class NestedType>
352 void RegisterNestedField(
353 const std::string& field_name, NestedType StructType::* field) {
354 fields_.push_back(new internal::FieldConverter<StructType, NestedType>(
355 field_name,
356 field,
357 new internal::NestedValueConverter<NestedType>));
358 }
359
[email protected]6009ca92012-01-13 02:18:02360 template <typename FieldType>
361 void RegisterCustomField(
362 const std::string& field_name,
363 FieldType StructType::* field,
364 bool (*convert_func)(const StringPiece&, FieldType*)) {
365 fields_.push_back(new internal::FieldConverter<StructType, FieldType>(
366 field_name,
367 field,
368 new internal::CustomFieldConverter<FieldType>(convert_func)));
369 }
370
[email protected]193f946b2011-12-22 18:31:47371 void RegisterRepeatedInt(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12372 ScopedVector<int> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47373 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12374 new internal::FieldConverter<StructType, ScopedVector<int> >(
[email protected]193f946b2011-12-22 18:31:47375 field_name, field, new internal::RepeatedValueConverter<int>));
376 }
377
378 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12379 ScopedVector<std::string> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47380 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12381 new internal::FieldConverter<StructType, ScopedVector<std::string> >(
[email protected]193f946b2011-12-22 18:31:47382 field_name,
383 field,
384 new internal::RepeatedValueConverter<std::string>));
385 }
386
[email protected]261c877e2012-01-05 09:46:42387 void RegisterRepeatedString(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12388 ScopedVector<string16> StructType::* field) {
[email protected]261c877e2012-01-05 09:46:42389 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12390 new internal::FieldConverter<StructType, ScopedVector<string16> >(
[email protected]261c877e2012-01-05 09:46:42391 field_name,
392 field,
393 new internal::RepeatedValueConverter<string16>));
394 }
395
[email protected]193f946b2011-12-22 18:31:47396 void RegisterRepeatedDouble(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12397 ScopedVector<double> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47398 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12399 new internal::FieldConverter<StructType, ScopedVector<double> >(
[email protected]193f946b2011-12-22 18:31:47400 field_name, field, new internal::RepeatedValueConverter<double>));
401 }
402
403 void RegisterRepeatedBool(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12404 ScopedVector<bool> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47405 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12406 new internal::FieldConverter<StructType, ScopedVector<bool> >(
[email protected]193f946b2011-12-22 18:31:47407 field_name, field, new internal::RepeatedValueConverter<bool>));
408 }
409
410 template <class NestedType>
411 void RegisterRepeatedMessage(const std::string& field_name,
[email protected]a9b8e0a2012-01-14 05:36:12412 ScopedVector<NestedType> StructType::* field) {
[email protected]193f946b2011-12-22 18:31:47413 fields_.push_back(
[email protected]a9b8e0a2012-01-14 05:36:12414 new internal::FieldConverter<StructType, ScopedVector<NestedType> >(
[email protected]193f946b2011-12-22 18:31:47415 field_name,
416 field,
417 new internal::RepeatedMessageConverter<NestedType>));
418 }
419
[email protected]261c877e2012-01-05 09:46:42420 bool Convert(const base::Value& value, StructType* output) const {
[email protected]193f946b2011-12-22 18:31:47421 const DictionaryValue* dictionary_value = NULL;
422 if (!value.GetAsDictionary(&dictionary_value))
[email protected]261c877e2012-01-05 09:46:42423 return false;
[email protected]193f946b2011-12-22 18:31:47424
[email protected]a9b8e0a2012-01-14 05:36:12425 for(size_t i = 0; i < fields_.size(); ++i) {
426 const internal::FieldConverterBase* field_converter = fields_[i];
[email protected]193f946b2011-12-22 18:31:47427 base::Value* field = NULL;
[email protected]a9b8e0a2012-01-14 05:36:12428 if (dictionary_value->Get(field_converter->field_path(), &field)) {
429 if (!field_converter->ConvertField(*field, output)) {
430 DVLOG(1) << "failure at field " << field_converter->field_path();
[email protected]261c877e2012-01-05 09:46:42431 return false;
432 }
[email protected]193f946b2011-12-22 18:31:47433 }
434 }
[email protected]261c877e2012-01-05 09:46:42435 return true;
[email protected]193f946b2011-12-22 18:31:47436 }
437
438 private:
[email protected]a9b8e0a2012-01-14 05:36:12439 ScopedVector<internal::FieldConverterBase> fields_;
[email protected]193f946b2011-12-22 18:31:47440
441 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
442};
443
444} // namespace base
445
446#endif // BASE_JSON_JSON_VALUE_CONVERTER_H_