| Index: base/json/json_value_converter.h
|
| diff --git a/base/json/json_value_converter.h b/base/json/json_value_converter.h
|
| index 64cd90b7aa6e9dfe84ea394655e3ee25ba13f775..7d8357fe9d7437cb6c98840393effec10a6dd437 100644
|
| --- a/base/json/json_value_converter.h
|
| +++ b/base/json/json_value_converter.h
|
| @@ -14,6 +14,7 @@
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/stl_util.h"
|
| +#include "base/string16.h"
|
| #include "base/values.h"
|
|
|
| // JSONValueConverter converts a JSON value into a C++ struct in a
|
| @@ -45,12 +46,18 @@
|
| // JSONValueConverter<Message> converter;
|
| // converter.Convert(json, &message);
|
| //
|
| +// Convert() returns false when it fails. Here "fail" means that the value is
|
| +// structurally different from expected, such like a string value appears
|
| +// for an int field. Do not report failures for missing fields.
|
| +// Also note that Convert() will modify the passed |message| even when it
|
| +// fails for performance reason.
|
| +//
|
| // For nested field, the internal message also has to implement the registration
|
| // method. Then, just use RegisterNestedField() from the containing struct's
|
| // RegisterJSONConverter method.
|
| // struct Nested {
|
| // Message foo;
|
| -// void RegisterJSONConverter(...) {
|
| +// static void RegisterJSONConverter(...) {
|
| // ...
|
| // converter->RegisterNestedField("foo", &Nested::foo);
|
| // }
|
| @@ -72,7 +79,7 @@ class FieldConverterBase {
|
| public:
|
| BASE_EXPORT explicit FieldConverterBase(const std::string& path);
|
| BASE_EXPORT virtual ~FieldConverterBase();
|
| - virtual void ConvertField(const base::Value& value, void* obj) const = 0;
|
| + virtual bool ConvertField(const base::Value& value, void* obj) const = 0;
|
| const std::string& field_path() const { return field_path_; }
|
|
|
| private:
|
| @@ -84,7 +91,7 @@ template <typename FieldType>
|
| class ValueConverter {
|
| public:
|
| virtual ~ValueConverter() {}
|
| - virtual void Convert(const base::Value& value, FieldType* field) const = 0;
|
| + virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
|
| };
|
|
|
| template <typename StructType, typename FieldType>
|
| @@ -98,10 +105,10 @@ class FieldConverter : public FieldConverterBase {
|
| value_converter_(converter) {
|
| }
|
|
|
| - virtual void ConvertField(
|
| + virtual bool ConvertField(
|
| const base::Value& value, void* obj) const OVERRIDE {
|
| StructType* dst = reinterpret_cast<StructType*>(obj);
|
| - value_converter_->Convert(value, &(dst->*field_pointer_));
|
| + return value_converter_->Convert(value, &(dst->*field_pointer_));
|
| }
|
|
|
| private:
|
| @@ -118,8 +125,8 @@ class BasicValueConverter<int> : public ValueConverter<int> {
|
| public:
|
| BasicValueConverter() {}
|
|
|
| - virtual void Convert(const base::Value& value, int* field) const OVERRIDE {
|
| - value.GetAsInteger(field);
|
| + virtual bool Convert(const base::Value& value, int* field) const OVERRIDE {
|
| + return value.GetAsInteger(field);
|
| }
|
|
|
| private:
|
| @@ -131,9 +138,23 @@ class BasicValueConverter<std::string> : public ValueConverter<std::string> {
|
| public:
|
| BasicValueConverter() {}
|
|
|
| - virtual void Convert(
|
| + virtual bool Convert(
|
| const base::Value& value, std::string* field) const OVERRIDE {
|
| - value.GetAsString(field);
|
| + return value.GetAsString(field);
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
|
| +};
|
| +
|
| +template <>
|
| +class BasicValueConverter<string16> : public ValueConverter<string16> {
|
| + public:
|
| + BasicValueConverter() {}
|
| +
|
| + virtual bool Convert(
|
| + const base::Value& value, string16* field) const OVERRIDE {
|
| + return value.GetAsString(field);
|
| }
|
|
|
| private:
|
| @@ -145,8 +166,8 @@ class BasicValueConverter<double> : public ValueConverter<double> {
|
| public:
|
| BasicValueConverter() {}
|
|
|
| - virtual void Convert(const base::Value& value, double* field) const OVERRIDE {
|
| - value.GetAsDouble(field);
|
| + virtual bool Convert(const base::Value& value, double* field) const OVERRIDE {
|
| + return value.GetAsDouble(field);
|
| }
|
|
|
| private:
|
| @@ -158,8 +179,8 @@ class BasicValueConverter<bool> : public ValueConverter<bool> {
|
| public:
|
| BasicValueConverter() {}
|
|
|
| - virtual void Convert(const base::Value& value, bool* field) const OVERRIDE {
|
| - value.GetAsBoolean(field);
|
| + virtual bool Convert(const base::Value& value, bool* field) const OVERRIDE {
|
| + return value.GetAsBoolean(field);
|
| }
|
|
|
| private:
|
| @@ -171,9 +192,9 @@ class NestedValueConverter : public ValueConverter<NestedType> {
|
| public:
|
| NestedValueConverter() {}
|
|
|
| - virtual void Convert(
|
| + virtual bool Convert(
|
| const base::Value& value, NestedType* field) const OVERRIDE {
|
| - converter_.Convert(value, field);
|
| + return converter_.Convert(value, field);
|
| }
|
|
|
| private:
|
| @@ -186,12 +207,12 @@ class RepeatedValueConverter : public ValueConverter<std::vector<Element> > {
|
| public:
|
| RepeatedValueConverter() {}
|
|
|
| - virtual void Convert(
|
| + virtual bool Convert(
|
| const base::Value& value, std::vector<Element>* field) const OVERRIDE {
|
| const base::ListValue* list = NULL;
|
| if (!value.GetAsList(&list)) {
|
| // The field is not a list.
|
| - return;
|
| + return false;
|
| }
|
|
|
| field->reserve(list->GetSize());
|
| @@ -201,9 +222,13 @@ class RepeatedValueConverter : public ValueConverter<std::vector<Element> > {
|
| continue;
|
|
|
| Element e;
|
| - basic_converter_.Convert(*element, &e);
|
| + if (!basic_converter_.Convert(*element, &e)) {
|
| + DVLOG(1) << "failure at " << i << "-th element";
|
| + return false;
|
| + }
|
| field->push_back(e);
|
| }
|
| + return true;
|
| }
|
|
|
| private:
|
| @@ -217,11 +242,11 @@ class RepeatedMessageConverter
|
| public:
|
| RepeatedMessageConverter() {}
|
|
|
| - virtual void Convert(
|
| + virtual bool Convert(
|
| const base::Value& value, std::vector<NestedType>* field) const OVERRIDE {
|
| const base::ListValue* list = NULL;
|
| if (!value.GetAsList(&list))
|
| - return;
|
| + return false;
|
|
|
| field->reserve(list->GetSize());
|
| for (size_t i = 0; i < list->GetSize(); ++i) {
|
| @@ -230,8 +255,12 @@ class RepeatedMessageConverter
|
| continue;
|
|
|
| field->push_back(NestedType());
|
| - converter_.Convert(*element, &field->back());
|
| + if (!converter_.Convert(*element, &field->back())) {
|
| + DVLOG(1) << "failure at " << i << "-th element";
|
| + return false;
|
| + }
|
| }
|
| + return true;
|
| }
|
|
|
| private:
|
| @@ -259,11 +288,17 @@ class JSONValueConverter {
|
| }
|
|
|
| void RegisterStringField(const std::string& field_name,
|
| - std::string StructType::* field) {
|
| + std::string StructType::* field) {
|
| fields_.push_back(new internal::FieldConverter<StructType, std::string>(
|
| field_name, field, new internal::BasicValueConverter<std::string>));
|
| }
|
|
|
| + void RegisterStringField(const std::string& field_name,
|
| + string16 StructType::* field) {
|
| + fields_.push_back(new internal::FieldConverter<StructType, string16>(
|
| + field_name, field, new internal::BasicValueConverter<string16>));
|
| + }
|
| +
|
| void RegisterBoolField(const std::string& field_name,
|
| bool StructType::* field) {
|
| fields_.push_back(new internal::FieldConverter<StructType, bool>(
|
| @@ -301,6 +336,15 @@ class JSONValueConverter {
|
| new internal::RepeatedValueConverter<std::string>));
|
| }
|
|
|
| + void RegisterRepeatedString(const std::string& field_name,
|
| + std::vector<string16> StructType::* field) {
|
| + fields_.push_back(
|
| + new internal::FieldConverter<StructType, std::vector<string16> >(
|
| + field_name,
|
| + field,
|
| + new internal::RepeatedValueConverter<string16>));
|
| + }
|
| +
|
| void RegisterRepeatedDouble(const std::string& field_name,
|
| std::vector<double> StructType::* field) {
|
| fields_.push_back(
|
| @@ -325,18 +369,22 @@ class JSONValueConverter {
|
| new internal::RepeatedMessageConverter<NestedType>));
|
| }
|
|
|
| - void Convert(const base::Value& value, StructType* output) const {
|
| + bool Convert(const base::Value& value, StructType* output) const {
|
| const DictionaryValue* dictionary_value = NULL;
|
| if (!value.GetAsDictionary(&dictionary_value))
|
| - return;
|
| + return false;
|
|
|
| for(std::vector<internal::FieldConverterBase*>::const_iterator it =
|
| fields_.begin(); it != fields_.end(); ++it) {
|
| base::Value* field = NULL;
|
| if (dictionary_value->Get((*it)->field_path(), &field)) {
|
| - (*it)->ConvertField(*field, output);
|
| + if (!(*it)->ConvertField(*field, output)) {
|
| + DVLOG(1) << "failure at field " << (*it)->field_path();
|
| + return false;
|
| + }
|
| }
|
| }
|
| + return true;
|
| }
|
|
|
| private:
|
|
|