123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef BASE_JSON_JSON_VALUE_CONVERTER_H_
- #define BASE_JSON_JSON_VALUE_CONVERTER_H_
- #include <stddef.h>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/base_export.h"
- #include "base/logging.h"
- #include "base/macros.h"
- #include "base/memory/ptr_util.h"
- #include "base/strings/string16.h"
- #include "base/strings/string_piece.h"
- #include "base/values.h"
- // JSONValueConverter converts a JSON value into a C++ struct in a
- // lightweight way.
- //
- // Usage:
- // For real examples, you may want to refer to _unittest.cc file.
- //
- // Assume that you have a struct like this:
- // struct Message {
- // int foo;
- // std::string bar;
- // static void RegisterJSONConverter(
- // JSONValueConverter<Message>* converter);
- // };
- //
- // And you want to parse a json data into this struct. First, you
- // need to declare RegisterJSONConverter() method in your struct.
- // // static
- // void Message::RegisterJSONConverter(
- // JSONValueConverter<Message>* converter) {
- // converter->RegisterIntField("foo", &Message::foo);
- // converter->RegisterStringField("bar", &Message::bar);
- // }
- //
- // Then, you just instantiate your JSONValueConverter of your type and call
- // Convert() method.
- // Message message;
- // 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;
- // static void RegisterJSONConverter(...) {
- // ...
- // converter->RegisterNestedField("foo", &Nested::foo);
- // }
- // };
- //
- // For repeated field, we just assume std::vector<std::unique_ptr<ElementType>>
- // for its container 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.
- // bool ConvertFunc(StringPiece s, YourEnum* result) {
- // // do something and return true if succeed...
- // }
- // struct Message {
- // YourEnum ye;
- // ...
- // static void RegisterJSONConverter(...) {
- // ...
- // converter->RegsiterCustomField<YourEnum>(
- // "your_enum", &Message::ye, &ConvertFunc);
- // }
- // };
- namespace base {
- template <typename StructType>
- class JSONValueConverter;
- namespace internal {
- template<typename StructType>
- class FieldConverterBase {
- public:
- explicit FieldConverterBase(const std::string& path) : field_path_(path) {}
- virtual ~FieldConverterBase() = default;
- virtual bool ConvertField(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);
- };
- template <typename FieldType>
- class ValueConverter {
- public:
- virtual ~ValueConverter() = default;
- virtual bool Convert(const base::Value& value, FieldType* field) const = 0;
- };
- template <typename StructType, typename FieldType>
- class FieldConverter : public FieldConverterBase<StructType> {
- public:
- explicit FieldConverter(const std::string& path,
- FieldType StructType::* field,
- ValueConverter<FieldType>* converter)
- : FieldConverterBase<StructType>(path),
- field_pointer_(field),
- value_converter_(converter) {
- }
- bool ConvertField(const base::Value& value, StructType* dst) const override {
- return value_converter_->Convert(value, &(dst->*field_pointer_));
- }
- private:
- FieldType StructType::* field_pointer_;
- std::unique_ptr<ValueConverter<FieldType>> value_converter_;
- DISALLOW_COPY_AND_ASSIGN(FieldConverter);
- };
- template <typename FieldType>
- class BasicValueConverter;
- template <>
- class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> {
- public:
- BasicValueConverter() = default;
- bool Convert(const base::Value& value, int* field) const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
- };
- template <>
- class BASE_EXPORT BasicValueConverter<std::string>
- : public ValueConverter<std::string> {
- public:
- BasicValueConverter() = default;
- bool Convert(const base::Value& value, std::string* field) const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
- };
- template <>
- class BASE_EXPORT BasicValueConverter<string16>
- : public ValueConverter<string16> {
- public:
- BasicValueConverter() = default;
- bool Convert(const base::Value& value, string16* field) const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
- };
- template <>
- class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> {
- public:
- BasicValueConverter() = default;
- bool Convert(const base::Value& value, double* field) const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
- };
- template <>
- class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> {
- public:
- BasicValueConverter() = default;
- bool Convert(const base::Value& value, bool* field) const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(BasicValueConverter);
- };
- template <typename FieldType>
- class ValueFieldConverter : public ValueConverter<FieldType> {
- public:
- typedef bool(*ConvertFunc)(const base::Value* value, FieldType* field);
- explicit ValueFieldConverter(ConvertFunc convert_func)
- : convert_func_(convert_func) {}
- bool Convert(const base::Value& value, FieldType* field) const override {
- return convert_func_(&value, field);
- }
- private:
- ConvertFunc convert_func_;
- DISALLOW_COPY_AND_ASSIGN(ValueFieldConverter);
- };
- template <typename FieldType>
- class CustomFieldConverter : public ValueConverter<FieldType> {
- public:
- typedef bool (*ConvertFunc)(StringPiece value, FieldType* field);
- explicit CustomFieldConverter(ConvertFunc convert_func)
- : convert_func_(convert_func) {}
- bool Convert(const base::Value& value, FieldType* field) const override {
- std::string string_value;
- return value.GetAsString(&string_value) &&
- convert_func_(string_value, field);
- }
- private:
- ConvertFunc convert_func_;
- DISALLOW_COPY_AND_ASSIGN(CustomFieldConverter);
- };
- template <typename NestedType>
- class NestedValueConverter : public ValueConverter<NestedType> {
- public:
- NestedValueConverter() = default;
- bool Convert(const base::Value& value, NestedType* field) const override {
- return converter_.Convert(value, field);
- }
- private:
- JSONValueConverter<NestedType> converter_;
- DISALLOW_COPY_AND_ASSIGN(NestedValueConverter);
- };
- template <typename Element>
- class RepeatedValueConverter
- : public ValueConverter<std::vector<std::unique_ptr<Element>>> {
- public:
- RepeatedValueConverter() = default;
- bool Convert(const base::Value& value,
- std::vector<std::unique_ptr<Element>>* field) const override {
- if (!value.is_list()) {
- // The field is not a list.
- return false;
- }
- field->reserve(value.GetList().size());
- size_t i = 0;
- for (const Value& element : value.GetList()) {
- auto e = std::make_unique<Element>();
- if (basic_converter_.Convert(element, e.get())) {
- field->push_back(std::move(e));
- } else {
- DVLOG(1) << "failure at " << i << "-th element";
- return false;
- }
- i++;
- }
- return true;
- }
- private:
- BasicValueConverter<Element> basic_converter_;
- DISALLOW_COPY_AND_ASSIGN(RepeatedValueConverter);
- };
- template <typename NestedType>
- class RepeatedMessageConverter
- : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> {
- public:
- RepeatedMessageConverter() = default;
- bool Convert(const base::Value& value,
- std::vector<std::unique_ptr<NestedType>>* field) const override {
- if (!value.is_list())
- return false;
- field->reserve(value.GetList().size());
- size_t i = 0;
- for (const Value& element : value.GetList()) {
- auto nested = std::make_unique<NestedType>();
- if (converter_.Convert(element, nested.get())) {
- field->push_back(std::move(nested));
- } else {
- DVLOG(1) << "failure at " << i << "-th element";
- return false;
- }
- i++;
- }
- return true;
- }
- private:
- JSONValueConverter<NestedType> converter_;
- DISALLOW_COPY_AND_ASSIGN(RepeatedMessageConverter);
- };
- template <typename NestedType>
- class RepeatedCustomValueConverter
- : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> {
- public:
- typedef bool(*ConvertFunc)(const base::Value* value, NestedType* field);
- explicit RepeatedCustomValueConverter(ConvertFunc convert_func)
- : convert_func_(convert_func) {}
- bool Convert(const base::Value& value,
- std::vector<std::unique_ptr<NestedType>>* field) const override {
- if (!value.is_list())
- return false;
- field->reserve(value.GetList().size());
- size_t i = 0;
- for (const Value& element : value.GetList()) {
- auto nested = std::make_unique<NestedType>();
- if ((*convert_func_)(&element, nested.get())) {
- field->push_back(std::move(nested));
- } else {
- DVLOG(1) << "failure at " << i << "-th element";
- return false;
- }
- i++;
- }
- return true;
- }
- private:
- ConvertFunc convert_func_;
- DISALLOW_COPY_AND_ASSIGN(RepeatedCustomValueConverter);
- };
- } // namespace internal
- template <class StructType>
- class JSONValueConverter {
- public:
- JSONValueConverter() {
- StructType::RegisterJSONConverter(this);
- }
- void RegisterIntField(const std::string& field_name,
- int StructType::* field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, int>>(
- field_name, field, new internal::BasicValueConverter<int>));
- }
- void RegisterStringField(const std::string& field_name,
- std::string StructType::* field) {
- fields_.push_back(
- std::make_unique<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(
- std::make_unique<internal::FieldConverter<StructType, string16>>(
- field_name, field, new internal::BasicValueConverter<string16>));
- }
- void RegisterBoolField(const std::string& field_name,
- bool StructType::* field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, bool>>(
- field_name, field, new internal::BasicValueConverter<bool>));
- }
- void RegisterDoubleField(const std::string& field_name,
- double StructType::* field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, double>>(
- field_name, field, new internal::BasicValueConverter<double>));
- }
- template <class NestedType>
- void RegisterNestedField(
- const std::string& field_name, NestedType StructType::* field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, NestedType>>(
- field_name, field, new internal::NestedValueConverter<NestedType>));
- }
- template <typename FieldType>
- void RegisterCustomField(const std::string& field_name,
- FieldType StructType::*field,
- bool (*convert_func)(StringPiece, FieldType*)) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, FieldType>>(
- field_name, field,
- new internal::CustomFieldConverter<FieldType>(convert_func)));
- }
- template <typename FieldType>
- void RegisterCustomValueField(
- const std::string& field_name,
- FieldType StructType::* field,
- bool (*convert_func)(const base::Value*, FieldType*)) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<StructType, FieldType>>(
- field_name, field,
- new internal::ValueFieldConverter<FieldType>(convert_func)));
- }
- void RegisterRepeatedInt(
- const std::string& field_name,
- std::vector<std::unique_ptr<int>> StructType::*field) {
- fields_.push_back(std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<int>>>>(
- field_name, field, new internal::RepeatedValueConverter<int>));
- }
- void RegisterRepeatedString(
- const std::string& field_name,
- std::vector<std::unique_ptr<std::string>> StructType::*field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<std::string>>>>(
- field_name, field,
- new internal::RepeatedValueConverter<std::string>));
- }
- void RegisterRepeatedString(
- const std::string& field_name,
- std::vector<std::unique_ptr<string16>> StructType::*field) {
- fields_.push_back(std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<string16>>>>(
- field_name, field, new internal::RepeatedValueConverter<string16>));
- }
- void RegisterRepeatedDouble(
- const std::string& field_name,
- std::vector<std::unique_ptr<double>> StructType::*field) {
- fields_.push_back(std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<double>>>>(
- field_name, field, new internal::RepeatedValueConverter<double>));
- }
- void RegisterRepeatedBool(
- const std::string& field_name,
- std::vector<std::unique_ptr<bool>> StructType::*field) {
- fields_.push_back(std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<bool>>>>(
- field_name, field, new internal::RepeatedValueConverter<bool>));
- }
- template <class NestedType>
- void RegisterRepeatedCustomValue(
- const std::string& field_name,
- std::vector<std::unique_ptr<NestedType>> StructType::*field,
- bool (*convert_func)(const base::Value*, NestedType*)) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<NestedType>>>>(
- field_name, field,
- new internal::RepeatedCustomValueConverter<NestedType>(
- convert_func)));
- }
- template <class NestedType>
- void RegisterRepeatedMessage(
- const std::string& field_name,
- std::vector<std::unique_ptr<NestedType>> StructType::*field) {
- fields_.push_back(
- std::make_unique<internal::FieldConverter<
- StructType, std::vector<std::unique_ptr<NestedType>>>>(
- field_name, field,
- new internal::RepeatedMessageConverter<NestedType>));
- }
- bool Convert(const base::Value& value, StructType* output) const {
- if (!value.is_dict())
- return false;
- for (size_t i = 0; i < fields_.size(); ++i) {
- const internal::FieldConverterBase<StructType>* field_converter =
- fields_[i].get();
- const base::Value* field = value.FindPath(field_converter->field_path());
- if (field) {
- if (!field_converter->ConvertField(*field, output)) {
- DVLOG(1) << "failure at field " << field_converter->field_path();
- return false;
- }
- }
- }
- return true;
- }
- private:
- std::vector<std::unique_ptr<internal::FieldConverterBase<StructType>>>
- fields_;
- DISALLOW_COPY_AND_ASSIGN(JSONValueConverter);
- };
- } // namespace base
- #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_
|