Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Unified Diff: base/json/json_value_converter.h

Issue 10440101: ABANDONED: Update base::JSONValueConverter to support custom actions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rename constants in test Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/json/json_value_converter.h
diff --git a/base/json/json_value_converter.h b/base/json/json_value_converter.h
index ff4271d476b4752ad1794dc1fe4565e58881ea04..034d80142eb63a5b21d6157667e815eaed8bf460 100644
--- a/base/json/json_value_converter.h
+++ b/base/json/json_value_converter.h
@@ -68,9 +68,9 @@
// and you can put RegisterRepeatedInt or some other types. Use
// RegisterRepeatedMessage for nested repeated fields.
//
-// Sometimes JSON format uses string representations for other types such
-// like enum, timestamp, or URL. You can use RegisterCustomField method
-// and specify a function to convert a StringPiece to your type.
+// Sometimes JSON format uses string representations for other types such like
+// enum, timestamp, or URL. You can use RegisterCustomField() and specify a
+// function to convert a StringPiece to your type.
// bool ConvertFunc(const StringPiece& s, YourEnum* result) {
// // do something and return true if succeed...
// }
@@ -79,10 +79,19 @@
// ...
// static void RegisterJSONConverter(...) {
// ...
-// converter->RegsiterCustomField<YourEnum>(
+// converter->RegisterCustomField<YourEnum>(
// "your_enum", &Message::ye, &ConvertFunc);
// }
// };
+//
+// If you want to perform an arbitrary action in response to a particular field
+// (e.g. perhaps it's a dictionary and you want to conditionally save one of its
+// fields to your message depending on the value of another of its fields),
+// RegisterCustomAction() can be used. If the field contains a list,
+// RegisterRepeatedCustomAction() can be used to specify that the handler
+// function should be invoked for each value in the list. Note that the handler
+// should still return true even if it takes no action; false should only be
+// returned if the data is malformed and conversion has failed.
namespace base {
@@ -91,54 +100,102 @@ class JSONValueConverter;
namespace internal {
-template<typename StructType>
-class FieldConverterBase {
+// Interface for classes that handle a base::Value located at a particular path.
+template <typename StructType>
+class FieldHandlerBase {
public:
- explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
- virtual ~FieldConverterBase() {}
- virtual bool ConvertField(const base::Value& value, StructType* obj)
+ explicit FieldHandlerBase(const std::string& path) : field_path_(path) {}
+ virtual ~FieldHandlerBase() {}
+ virtual bool HandleField(const base::Value& value, StructType* obj)
const = 0;
const std::string& field_path() const { return field_path_; }
private:
std::string field_path_;
- DISALLOW_COPY_AND_ASSIGN(FieldConverterBase);
+ DISALLOW_COPY_AND_ASSIGN(FieldHandlerBase);
};
+// Interface for classes that convert base::Values as needed and write them to
+// passed-in fields.
template <typename FieldType>
-class ValueConverter {
+class ValueConverterBase {
public:
- virtual ~ValueConverter() {}
+ virtual ~ValueConverterBase() {}
virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
};
+// FieldHandlerBase implementation that uses a ValueConverterBase to convert a
+// base::Value and write it to a passed-in field.
template <typename StructType, typename FieldType>
-class FieldConverter : public FieldConverterBase<StructType> {
+class FieldConverter : public FieldHandlerBase<StructType> {
public:
- explicit FieldConverter(const std::string& path,
- FieldType StructType::* field,
- ValueConverter<FieldType>* converter)
- : FieldConverterBase<StructType>(path),
+ FieldConverter(const std::string& path,
+ FieldType StructType::* field,
+ ValueConverterBase<FieldType>* converter)
+ : FieldHandlerBase<StructType>(path),
field_pointer_(field),
value_converter_(converter) {
}
- virtual bool ConvertField(
+ virtual bool HandleField(
const base::Value& value, StructType* dst) const OVERRIDE {
return value_converter_->Convert(value, &(dst->*field_pointer_));
}
private:
FieldType StructType::* field_pointer_;
- scoped_ptr<ValueConverter<FieldType> > value_converter_;
+ scoped_ptr<ValueConverterBase<FieldType> > value_converter_;
DISALLOW_COPY_AND_ASSIGN(FieldConverter);
};
+// FieldHandlerBase implementation that passes the bare base::Value and the
+// destination object (as opposed to a field within the object) to a function
+// that can process and apply the value however it wants.
+template <typename StructType>
+class FieldActionRunner : public FieldHandlerBase<StructType> {
+ public:
+ typedef bool(*ActionFunc)(const base::Value* value, StructType* obj);
+
+ // If |repeated| is true, the field is expected to contain a list.
+ // |action_func| will be invoked with each of its elements.
+ FieldActionRunner(const std::string& path,
+ bool repeated,
+ ActionFunc action_func)
+ : FieldHandlerBase<StructType>(path),
+ repeated_(repeated),
+ action_func_(action_func) {
+ }
+
+ virtual bool HandleField(const base::Value& value,
+ StructType* obj) const OVERRIDE {
+ if (!repeated_) {
+ return action_func_(&value, obj);
+ } else {
+ const base::ListValue* list = NULL;
+ if (!value.GetAsList(&list))
+ return false;
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ base::Value* element = NULL;
+ CHECK(list->Get(i, &element));
+ if (!action_func_(element, obj))
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private:
+ bool repeated_;
+ ActionFunc action_func_;
+ DISALLOW_COPY_AND_ASSIGN(FieldActionRunner);
+};
+
template <typename FieldType>
class BasicValueConverter;
template <>
-class BasicValueConverter<int> : public ValueConverter<int> {
+class BasicValueConverter<int> : public ValueConverterBase<int> {
public:
BasicValueConverter() {}
@@ -151,7 +208,8 @@ class BasicValueConverter<int> : public ValueConverter<int> {
};
template <>
-class BasicValueConverter<std::string> : public ValueConverter<std::string> {
+class BasicValueConverter<std::string>
+ : public ValueConverterBase<std::string> {
public:
BasicValueConverter() {}
@@ -165,7 +223,7 @@ class BasicValueConverter<std::string> : public ValueConverter<std::string> {
};
template <>
-class BasicValueConverter<string16> : public ValueConverter<string16> {
+class BasicValueConverter<string16> : public ValueConverterBase<string16> {
public:
BasicValueConverter() {}
@@ -179,7 +237,7 @@ class BasicValueConverter<string16> : public ValueConverter<string16> {
};
template <>
-class BasicValueConverter<double> : public ValueConverter<double> {
+class BasicValueConverter<double> : public ValueConverterBase<double> {
public:
BasicValueConverter() {}
@@ -192,7 +250,7 @@ class BasicValueConverter<double> : public ValueConverter<double> {
};
template <>
-class BasicValueConverter<bool> : public ValueConverter<bool> {
+class BasicValueConverter<bool> : public ValueConverterBase<bool> {
public:
BasicValueConverter() {}
@@ -205,7 +263,7 @@ class BasicValueConverter<bool> : public ValueConverter<bool> {
};
template <typename FieldType>
-class ValueFieldConverter : public ValueConverter<FieldType> {
+class ValueFieldConverter : public ValueConverterBase<FieldType> {
public:
typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
@@ -224,7 +282,7 @@ class ValueFieldConverter : public ValueConverter<FieldType> {
};
template <typename FieldType>
-class CustomFieldConverter : public ValueConverter<FieldType> {
+class CustomFieldConverter : public ValueConverterBase<FieldType> {
public:
typedef bool(*ConvertFunc)(const StringPiece& value, FieldType* field);
@@ -245,7 +303,7 @@ class CustomFieldConverter : public ValueConverter<FieldType> {
};
template <typename NestedType>
-class NestedValueConverter : public ValueConverter<NestedType> {
+class NestedValueConverter : public ValueConverterBase<NestedType> {
public:
NestedValueConverter() {}
@@ -260,7 +318,8 @@ class NestedValueConverter : public ValueConverter<NestedType> {
};
template <typename Element>
-class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
+class RepeatedValueConverter
+ : public ValueConverterBase<ScopedVector<Element> > {
public:
RepeatedValueConverter() {}
@@ -275,8 +334,7 @@ class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
field->reserve(list->GetSize());
for (size_t i = 0; i < list->GetSize(); ++i) {
base::Value* element = NULL;
- if (!list->Get(i, &element))
- continue;
+ CHECK(list->Get(i, &element));
scoped_ptr<Element> e(new Element);
if (basic_converter_.Convert(*element, e.get())) {
@@ -296,7 +354,7 @@ class RepeatedValueConverter : public ValueConverter<ScopedVector<Element> > {
template <typename NestedType>
class RepeatedMessageConverter
- : public ValueConverter<ScopedVector<NestedType> > {
+ : public ValueConverterBase<ScopedVector<NestedType> > {
public:
RepeatedMessageConverter() {}
@@ -309,8 +367,7 @@ class RepeatedMessageConverter
field->reserve(list->GetSize());
for (size_t i = 0; i < list->GetSize(); ++i) {
base::Value* element = NULL;
- if (!list->Get(i, &element))
- continue;
+ CHECK(list->Get(i, &element));
scoped_ptr<NestedType> nested(new NestedType);
if (converter_.Convert(*element, nested.get())) {
@@ -330,7 +387,7 @@ class RepeatedMessageConverter
template <typename NestedType>
class RepeatedCustomValueConverter
- : public ValueConverter<ScopedVector<NestedType> > {
+ : public ValueConverterBase<ScopedVector<NestedType> > {
public:
typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
@@ -346,8 +403,7 @@ class RepeatedCustomValueConverter
field->reserve(list->GetSize());
for (size_t i = 0; i < list->GetSize(); ++i) {
base::Value* element = NULL;
- if (!list->Get(i, &element))
- continue;
+ CHECK(list->Get(i, &element));
scoped_ptr<NestedType> nested(new NestedType);
if ((*convert_func_)(element, nested.get())) {
@@ -436,6 +492,15 @@ class JSONValueConverter {
new internal::ValueFieldConverter<FieldType>(convert_func)));
}
+ void RegisterCustomAction(
+ const std::string& field_name,
+ bool (*action_func)(const base::Value*, StructType*)) {
+ fields_.push_back(new internal::FieldActionRunner<StructType>(
+ field_name,
+ false, // repeated
+ action_func));
+ }
+
void RegisterRepeatedInt(const std::string& field_name,
ScopedVector<int> StructType::* field) {
fields_.push_back(
@@ -498,18 +563,26 @@ class JSONValueConverter {
new internal::RepeatedMessageConverter<NestedType>));
}
+ void RegisterRepeatedCustomAction(
+ const std::string& field_name,
+ bool (*action_func)(const base::Value*, StructType*)) {
+ fields_.push_back(new internal::FieldActionRunner<StructType>(
+ field_name,
+ true, // repeated
+ action_func));
+ }
+
bool Convert(const base::Value& value, StructType* output) const {
const DictionaryValue* dictionary_value = NULL;
if (!value.GetAsDictionary(&dictionary_value))
return false;
for(size_t i = 0; i < fields_.size(); ++i) {
- const internal::FieldConverterBase<StructType>* field_converter =
- fields_[i];
+ const internal::FieldHandlerBase<StructType>* field_handler = fields_[i];
base::Value* field = NULL;
- if (dictionary_value->Get(field_converter->field_path(), &field)) {
- if (!field_converter->ConvertField(*field, output)) {
- DVLOG(1) << "failure at field " << field_converter->field_path();
+ if (dictionary_value->Get(field_handler->field_path(), &field)) {
+ if (!field_handler->HandleField(*field, output)) {
+ DVLOG(1) << "failure at field " << field_handler->field_path();
return false;
}
}
@@ -518,7 +591,7 @@ class JSONValueConverter {
}
private:
- ScopedVector<internal::FieldConverterBase<StructType> > fields_;
+ ScopedVector<internal::FieldHandlerBase<StructType> > fields_;
DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
};
« no previous file with comments | « no previous file | base/json/json_value_converter_unittest.cc » ('j') | base/json/json_value_converter_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698