OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_ | 5 #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_ |
6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_ | 6 #define BASE_JSON_JSON_VALUE_CONVERTER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/base_export.h" | 12 #include "base/base_export.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/string16.h" |
17 #include "base/values.h" | 18 #include "base/values.h" |
18 | 19 |
19 // JSONValueConverter converts a JSON value into a C++ struct in a | 20 // JSONValueConverter converts a JSON value into a C++ struct in a |
20 // lightweight way. | 21 // lightweight way. |
21 // | 22 // |
22 // Usage: | 23 // Usage: |
23 // For real examples, you may want to refer to _unittest.cc file. | 24 // For real examples, you may want to refer to _unittest.cc file. |
24 // | 25 // |
25 // Assume that you have a struct like this: | 26 // Assume that you have a struct like this: |
26 // struct Message { | 27 // struct Message { |
(...skipping 11 matching lines...) Expand all Loading... |
38 // converter->RegisterIntField("foo", &Message::foo); | 39 // converter->RegisterIntField("foo", &Message::foo); |
39 // converter->RegisterStringField("bar", &Message::bar); | 40 // converter->RegisterStringField("bar", &Message::bar); |
40 // } | 41 // } |
41 // | 42 // |
42 // Then, you just instantiate your JSONValueConverter of your type and call | 43 // Then, you just instantiate your JSONValueConverter of your type and call |
43 // Convert() method. | 44 // Convert() method. |
44 // Message message; | 45 // Message message; |
45 // JSONValueConverter<Message> converter; | 46 // JSONValueConverter<Message> converter; |
46 // converter.Convert(json, &message); | 47 // converter.Convert(json, &message); |
47 // | 48 // |
| 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. |
| 54 // |
48 // For nested field, the internal message also has to implement the registration | 55 // For nested field, the internal message also has to implement the registration |
49 // method. Then, just use RegisterNestedField() from the containing struct's | 56 // method. Then, just use RegisterNestedField() from the containing struct's |
50 // RegisterJSONConverter method. | 57 // RegisterJSONConverter method. |
51 // struct Nested { | 58 // struct Nested { |
52 // Message foo; | 59 // Message foo; |
53 // void RegisterJSONConverter(...) { | 60 // static void RegisterJSONConverter(...) { |
54 // ... | 61 // ... |
55 // converter->RegisterNestedField("foo", &Nested::foo); | 62 // converter->RegisterNestedField("foo", &Nested::foo); |
56 // } | 63 // } |
57 // }; | 64 // }; |
58 // | 65 // |
59 // For repeated field, we just assume std::vector for its container | 66 // For repeated field, we just assume std::vector for its container |
60 // and you can put RegisterRepeatedInt or some other types. Use | 67 // and you can put RegisterRepeatedInt or some other types. Use |
61 // RegisterRepeatedMessage for nested repeated fields. | 68 // RegisterRepeatedMessage for nested repeated fields. |
62 // | 69 // |
63 | 70 |
64 namespace base { | 71 namespace base { |
65 | 72 |
66 template <typename StructType> | 73 template <typename StructType> |
67 class JSONValueConverter; | 74 class JSONValueConverter; |
68 | 75 |
69 namespace internal { | 76 namespace internal { |
70 | 77 |
71 class FieldConverterBase { | 78 class FieldConverterBase { |
72 public: | 79 public: |
73 BASE_EXPORT explicit FieldConverterBase(const std::string& path); | 80 BASE_EXPORT explicit FieldConverterBase(const std::string& path); |
74 BASE_EXPORT virtual ~FieldConverterBase(); | 81 BASE_EXPORT virtual ~FieldConverterBase(); |
75 virtual void ConvertField(const base::Value& value, void* obj) const = 0; | 82 virtual bool ConvertField(const base::Value& value, void* obj) const = 0; |
76 const std::string& field_path() const { return field_path_; } | 83 const std::string& field_path() const { return field_path_; } |
77 | 84 |
78 private: | 85 private: |
79 std::string field_path_; | 86 std::string field_path_; |
80 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase); | 87 DISALLOW_COPY_AND_ASSIGN(FieldConverterBase); |
81 }; | 88 }; |
82 | 89 |
83 template <typename FieldType> | 90 template <typename FieldType> |
84 class ValueConverter { | 91 class ValueConverter { |
85 public: | 92 public: |
86 virtual ~ValueConverter() {} | 93 virtual ~ValueConverter() {} |
87 virtual void Convert(const base::Value& value, FieldType* field) const = 0; | 94 virtual bool Convert(const base::Value& value, FieldType* field) const = 0; |
88 }; | 95 }; |
89 | 96 |
90 template <typename StructType, typename FieldType> | 97 template <typename StructType, typename FieldType> |
91 class FieldConverter : public FieldConverterBase { | 98 class FieldConverter : public FieldConverterBase { |
92 public: | 99 public: |
93 explicit FieldConverter(const std::string& path, | 100 explicit FieldConverter(const std::string& path, |
94 FieldType StructType::* field, | 101 FieldType StructType::* field, |
95 ValueConverter<FieldType>* converter) | 102 ValueConverter<FieldType>* converter) |
96 : FieldConverterBase(path), | 103 : FieldConverterBase(path), |
97 field_pointer_(field), | 104 field_pointer_(field), |
98 value_converter_(converter) { | 105 value_converter_(converter) { |
99 } | 106 } |
100 | 107 |
101 virtual void ConvertField( | 108 virtual bool ConvertField( |
102 const base::Value& value, void* obj) const OVERRIDE { | 109 const base::Value& value, void* obj) const OVERRIDE { |
103 StructType* dst = reinterpret_cast<StructType*>(obj); | 110 StructType* dst = reinterpret_cast<StructType*>(obj); |
104 value_converter_->Convert(value, &(dst->*field_pointer_)); | 111 return value_converter_->Convert(value, &(dst->*field_pointer_)); |
105 } | 112 } |
106 | 113 |
107 private: | 114 private: |
108 FieldType StructType::* field_pointer_; | 115 FieldType StructType::* field_pointer_; |
109 scoped_ptr<ValueConverter<FieldType> > value_converter_; | 116 scoped_ptr<ValueConverter<FieldType> > value_converter_; |
110 DISALLOW_COPY_AND_ASSIGN(FieldConverter); | 117 DISALLOW_COPY_AND_ASSIGN(FieldConverter); |
111 }; | 118 }; |
112 | 119 |
113 template <typename FieldType> | 120 template <typename FieldType> |
114 class BasicValueConverter; | 121 class BasicValueConverter; |
115 | 122 |
116 template <> | 123 template <> |
117 class BasicValueConverter<int> : public ValueConverter<int> { | 124 class BasicValueConverter<int> : public ValueConverter<int> { |
118 public: | 125 public: |
119 BasicValueConverter() {} | 126 BasicValueConverter() {} |
120 | 127 |
121 virtual void Convert(const base::Value& value, int* field) const OVERRIDE { | 128 virtual bool Convert(const base::Value& value, int* field) const OVERRIDE { |
122 value.GetAsInteger(field); | 129 return value.GetAsInteger(field); |
123 } | 130 } |
124 | 131 |
125 private: | 132 private: |
126 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); | 133 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); |
127 }; | 134 }; |
128 | 135 |
129 template <> | 136 template <> |
130 class BasicValueConverter<std::string> : public ValueConverter<std::string> { | 137 class BasicValueConverter<std::string> : public ValueConverter<std::string> { |
131 public: | 138 public: |
132 BasicValueConverter() {} | 139 BasicValueConverter() {} |
133 | 140 |
134 virtual void Convert( | 141 virtual bool Convert( |
135 const base::Value& value, std::string* field) const OVERRIDE { | 142 const base::Value& value, std::string* field) const OVERRIDE { |
136 value.GetAsString(field); | 143 return value.GetAsString(field); |
137 } | 144 } |
138 | 145 |
139 private: | 146 private: |
| 147 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); |
| 148 }; |
| 149 |
| 150 template <> |
| 151 class BasicValueConverter<string16> : public ValueConverter<string16> { |
| 152 public: |
| 153 BasicValueConverter() {} |
| 154 |
| 155 virtual bool Convert( |
| 156 const base::Value& value, string16* field) const OVERRIDE { |
| 157 return value.GetAsString(field); |
| 158 } |
| 159 |
| 160 private: |
140 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); | 161 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); |
141 }; | 162 }; |
142 | 163 |
143 template <> | 164 template <> |
144 class BasicValueConverter<double> : public ValueConverter<double> { | 165 class BasicValueConverter<double> : public ValueConverter<double> { |
145 public: | 166 public: |
146 BasicValueConverter() {} | 167 BasicValueConverter() {} |
147 | 168 |
148 virtual void Convert(const base::Value& value, double* field) const OVERRIDE { | 169 virtual bool Convert(const base::Value& value, double* field) const OVERRIDE { |
149 value.GetAsDouble(field); | 170 return value.GetAsDouble(field); |
150 } | 171 } |
151 | 172 |
152 private: | 173 private: |
153 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); | 174 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); |
154 }; | 175 }; |
155 | 176 |
156 template <> | 177 template <> |
157 class BasicValueConverter<bool> : public ValueConverter<bool> { | 178 class BasicValueConverter<bool> : public ValueConverter<bool> { |
158 public: | 179 public: |
159 BasicValueConverter() {} | 180 BasicValueConverter() {} |
160 | 181 |
161 virtual void Convert(const base::Value& value, bool* field) const OVERRIDE { | 182 virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE { |
162 value.GetAsBoolean(field); | 183 return value.GetAsBoolean(field); |
163 } | 184 } |
164 | 185 |
165 private: | 186 private: |
166 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); | 187 DISALLOW_COPY_AND_ASSIGN(BasicValueConverter); |
167 }; | 188 }; |
168 | 189 |
169 template <typename NestedType> | 190 template <typename NestedType> |
170 class NestedValueConverter : public ValueConverter<NestedType> { | 191 class NestedValueConverter : public ValueConverter<NestedType> { |
171 public: | 192 public: |
172 NestedValueConverter() {} | 193 NestedValueConverter() {} |
173 | 194 |
174 virtual void Convert( | 195 virtual bool Convert( |
175 const base::Value& value, NestedType* field) const OVERRIDE { | 196 const base::Value& value, NestedType* field) const OVERRIDE { |
176 converter_.Convert(value, field); | 197 return converter_.Convert(value, field); |
177 } | 198 } |
178 | 199 |
179 private: | 200 private: |
180 JSONValueConverter<NestedType> converter_; | 201 JSONValueConverter<NestedType> converter_; |
181 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter); | 202 DISALLOW_COPY_AND_ASSIGN(NestedValueConverter); |
182 }; | 203 }; |
183 | 204 |
184 template <typename Element> | 205 template <typename Element> |
185 class RepeatedValueConverter : public ValueConverter<std::vector<Element> > { | 206 class RepeatedValueConverter : public ValueConverter<std::vector<Element> > { |
186 public: | 207 public: |
187 RepeatedValueConverter() {} | 208 RepeatedValueConverter() {} |
188 | 209 |
189 virtual void Convert( | 210 virtual bool Convert( |
190 const base::Value& value, std::vector<Element>* field) const OVERRIDE { | 211 const base::Value& value, std::vector<Element>* field) const OVERRIDE { |
191 const base::ListValue* list = NULL; | 212 const base::ListValue* list = NULL; |
192 if (!value.GetAsList(&list)) { | 213 if (!value.GetAsList(&list)) { |
193 // The field is not a list. | 214 // The field is not a list. |
194 return; | 215 return false; |
195 } | 216 } |
196 | 217 |
197 field->reserve(list->GetSize()); | 218 field->reserve(list->GetSize()); |
198 for (size_t i = 0; i < list->GetSize(); ++i) { | 219 for (size_t i = 0; i < list->GetSize(); ++i) { |
199 base::Value* element = NULL; | 220 base::Value* element = NULL; |
200 if (!list->Get(i, &element)) | 221 if (!list->Get(i, &element)) |
201 continue; | 222 continue; |
202 | 223 |
203 Element e; | 224 Element e; |
204 basic_converter_.Convert(*element, &e); | 225 if (!basic_converter_.Convert(*element, &e)) { |
| 226 DVLOG(1) << "failure at " << i << "-th element"; |
| 227 return false; |
| 228 } |
205 field->push_back(e); | 229 field->push_back(e); |
206 } | 230 } |
| 231 return true; |
207 } | 232 } |
208 | 233 |
209 private: | 234 private: |
210 BasicValueConverter<Element> basic_converter_; | 235 BasicValueConverter<Element> basic_converter_; |
211 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter); | 236 DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter); |
212 }; | 237 }; |
213 | 238 |
214 template <typename NestedType> | 239 template <typename NestedType> |
215 class RepeatedMessageConverter | 240 class RepeatedMessageConverter |
216 : public ValueConverter<std::vector<NestedType> > { | 241 : public ValueConverter<std::vector<NestedType> > { |
217 public: | 242 public: |
218 RepeatedMessageConverter() {} | 243 RepeatedMessageConverter() {} |
219 | 244 |
220 virtual void Convert( | 245 virtual bool Convert( |
221 const base::Value& value, std::vector<NestedType>* field) const OVERRIDE { | 246 const base::Value& value, std::vector<NestedType>* field) const OVERRIDE { |
222 const base::ListValue* list = NULL; | 247 const base::ListValue* list = NULL; |
223 if (!value.GetAsList(&list)) | 248 if (!value.GetAsList(&list)) |
224 return; | 249 return false; |
225 | 250 |
226 field->reserve(list->GetSize()); | 251 field->reserve(list->GetSize()); |
227 for (size_t i = 0; i < list->GetSize(); ++i) { | 252 for (size_t i = 0; i < list->GetSize(); ++i) { |
228 base::Value* element = NULL; | 253 base::Value* element = NULL; |
229 if (!list->Get(i, &element)) | 254 if (!list->Get(i, &element)) |
230 continue; | 255 continue; |
231 | 256 |
232 field->push_back(NestedType()); | 257 field->push_back(NestedType()); |
233 converter_.Convert(*element, &field->back()); | 258 if (!converter_.Convert(*element, &field->back())) { |
| 259 DVLOG(1) << "failure at " << i << "-th element"; |
| 260 return false; |
| 261 } |
234 } | 262 } |
| 263 return true; |
235 } | 264 } |
236 | 265 |
237 private: | 266 private: |
238 JSONValueConverter<NestedType> converter_; | 267 JSONValueConverter<NestedType> converter_; |
239 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter); | 268 DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter); |
240 }; | 269 }; |
241 | 270 |
242 } // namespace internal | 271 } // namespace internal |
243 | 272 |
244 template <class StructType> | 273 template <class StructType> |
245 class JSONValueConverter { | 274 class JSONValueConverter { |
246 public: | 275 public: |
247 JSONValueConverter() { | 276 JSONValueConverter() { |
248 StructType::RegisterJSONConverter(this); | 277 StructType::RegisterJSONConverter(this); |
249 } | 278 } |
250 | 279 |
251 ~JSONValueConverter() { | 280 ~JSONValueConverter() { |
252 STLDeleteContainerPointers(fields_.begin(), fields_.end()); | 281 STLDeleteContainerPointers(fields_.begin(), fields_.end()); |
253 } | 282 } |
254 | 283 |
255 void RegisterIntField(const std::string& field_name, | 284 void RegisterIntField(const std::string& field_name, |
256 int StructType::* field) { | 285 int StructType::* field) { |
257 fields_.push_back(new internal::FieldConverter<StructType, int>( | 286 fields_.push_back(new internal::FieldConverter<StructType, int>( |
258 field_name, field, new internal::BasicValueConverter<int>)); | 287 field_name, field, new internal::BasicValueConverter<int>)); |
259 } | 288 } |
260 | 289 |
261 void RegisterStringField(const std::string& field_name, | 290 void RegisterStringField(const std::string& field_name, |
262 std::string StructType::* field) { | 291 std::string StructType::* field) { |
263 fields_.push_back(new internal::FieldConverter<StructType, std::string>( | 292 fields_.push_back(new internal::FieldConverter<StructType, std::string>( |
264 field_name, field, new internal::BasicValueConverter<std::string>)); | 293 field_name, field, new internal::BasicValueConverter<std::string>)); |
265 } | 294 } |
266 | 295 |
| 296 void RegisterStringField(const std::string& field_name, |
| 297 string16 StructType::* field) { |
| 298 fields_.push_back(new internal::FieldConverter<StructType, string16>( |
| 299 field_name, field, new internal::BasicValueConverter<string16>)); |
| 300 } |
| 301 |
267 void RegisterBoolField(const std::string& field_name, | 302 void RegisterBoolField(const std::string& field_name, |
268 bool StructType::* field) { | 303 bool StructType::* field) { |
269 fields_.push_back(new internal::FieldConverter<StructType, bool>( | 304 fields_.push_back(new internal::FieldConverter<StructType, bool>( |
270 field_name, field, new internal::BasicValueConverter<bool>)); | 305 field_name, field, new internal::BasicValueConverter<bool>)); |
271 } | 306 } |
272 | 307 |
273 void RegisterDoubleField(const std::string& field_name, | 308 void RegisterDoubleField(const std::string& field_name, |
274 double StructType::* field) { | 309 double StructType::* field) { |
275 fields_.push_back(new internal::FieldConverter<StructType, double>( | 310 fields_.push_back(new internal::FieldConverter<StructType, double>( |
276 field_name, field, new internal::BasicValueConverter<double>)); | 311 field_name, field, new internal::BasicValueConverter<double>)); |
(...skipping 17 matching lines...) Expand all Loading... |
294 | 329 |
295 void RegisterRepeatedString(const std::string& field_name, | 330 void RegisterRepeatedString(const std::string& field_name, |
296 std::vector<std::string> StructType::* field) { | 331 std::vector<std::string> StructType::* field) { |
297 fields_.push_back( | 332 fields_.push_back( |
298 new internal::FieldConverter<StructType, std::vector<std::string> >( | 333 new internal::FieldConverter<StructType, std::vector<std::string> >( |
299 field_name, | 334 field_name, |
300 field, | 335 field, |
301 new internal::RepeatedValueConverter<std::string>)); | 336 new internal::RepeatedValueConverter<std::string>)); |
302 } | 337 } |
303 | 338 |
| 339 void RegisterRepeatedString(const std::string& field_name, |
| 340 std::vector<string16> StructType::* field) { |
| 341 fields_.push_back( |
| 342 new internal::FieldConverter<StructType, std::vector<string16> >( |
| 343 field_name, |
| 344 field, |
| 345 new internal::RepeatedValueConverter<string16>)); |
| 346 } |
| 347 |
304 void RegisterRepeatedDouble(const std::string& field_name, | 348 void RegisterRepeatedDouble(const std::string& field_name, |
305 std::vector<double> StructType::* field) { | 349 std::vector<double> StructType::* field) { |
306 fields_.push_back( | 350 fields_.push_back( |
307 new internal::FieldConverter<StructType, std::vector<double> >( | 351 new internal::FieldConverter<StructType, std::vector<double> >( |
308 field_name, field, new internal::RepeatedValueConverter<double>)); | 352 field_name, field, new internal::RepeatedValueConverter<double>)); |
309 } | 353 } |
310 | 354 |
311 void RegisterRepeatedBool(const std::string& field_name, | 355 void RegisterRepeatedBool(const std::string& field_name, |
312 std::vector<bool> StructType::* field) { | 356 std::vector<bool> StructType::* field) { |
313 fields_.push_back( | 357 fields_.push_back( |
314 new internal::FieldConverter<StructType, std::vector<bool> >( | 358 new internal::FieldConverter<StructType, std::vector<bool> >( |
315 field_name, field, new internal::RepeatedValueConverter<bool>)); | 359 field_name, field, new internal::RepeatedValueConverter<bool>)); |
316 } | 360 } |
317 | 361 |
318 template <class NestedType> | 362 template <class NestedType> |
319 void RegisterRepeatedMessage(const std::string& field_name, | 363 void RegisterRepeatedMessage(const std::string& field_name, |
320 std::vector<NestedType> StructType::* field) { | 364 std::vector<NestedType> StructType::* field) { |
321 fields_.push_back( | 365 fields_.push_back( |
322 new internal::FieldConverter<StructType, std::vector<NestedType> >( | 366 new internal::FieldConverter<StructType, std::vector<NestedType> >( |
323 field_name, | 367 field_name, |
324 field, | 368 field, |
325 new internal::RepeatedMessageConverter<NestedType>)); | 369 new internal::RepeatedMessageConverter<NestedType>)); |
326 } | 370 } |
327 | 371 |
328 void Convert(const base::Value& value, StructType* output) const { | 372 bool Convert(const base::Value& value, StructType* output) const { |
329 const DictionaryValue* dictionary_value = NULL; | 373 const DictionaryValue* dictionary_value = NULL; |
330 if (!value.GetAsDictionary(&dictionary_value)) | 374 if (!value.GetAsDictionary(&dictionary_value)) |
331 return; | 375 return false; |
332 | 376 |
333 for(std::vector<internal::FieldConverterBase*>::const_iterator it = | 377 for(std::vector<internal::FieldConverterBase*>::const_iterator it = |
334 fields_.begin(); it != fields_.end(); ++it) { | 378 fields_.begin(); it != fields_.end(); ++it) { |
335 base::Value* field = NULL; | 379 base::Value* field = NULL; |
336 if (dictionary_value->Get((*it)->field_path(), &field)) { | 380 if (dictionary_value->Get((*it)->field_path(), &field)) { |
337 (*it)->ConvertField(*field, output); | 381 if (!(*it)->ConvertField(*field, output)) { |
| 382 DVLOG(1) << "failure at field " << (*it)->field_path(); |
| 383 return false; |
| 384 } |
338 } | 385 } |
339 } | 386 } |
| 387 return true; |
340 } | 388 } |
341 | 389 |
342 private: | 390 private: |
343 std::vector<internal::FieldConverterBase*> fields_; | 391 std::vector<internal::FieldConverterBase*> fields_; |
344 | 392 |
345 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter); | 393 DISALLOW_COPY_AND_ASSIGN(JSONValueConverter); |
346 }; | 394 }; |
347 | 395 |
348 } // namespace base | 396 } // namespace base |
349 | 397 |
350 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ | 398 #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_ |
OLD | NEW |