// Copyright 2012 The Chromium Authors // 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 <string_view> #include <utility> #include <vector> #include "base/base_export.h" #include "base/logging.h" #include "base/memory/ptr_util.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 std::string_view to your type. // bool ConvertFunc(std::string_view 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 { … }; template <typename FieldType> class ValueConverter { … }; template <typename StructType, typename FieldType> class FieldConverter : public FieldConverterBase<StructType> { … }; template <typename FieldType> class BasicValueConverter; template <> class BASE_EXPORT BasicValueConverter<int> : public ValueConverter<int> { … }; template <> class BASE_EXPORT BasicValueConverter<std::string> : public ValueConverter<std::string> { … }; template <> class BASE_EXPORT BasicValueConverter<std::u16string> : public ValueConverter<std::u16string> { … }; template <> class BASE_EXPORT BasicValueConverter<double> : public ValueConverter<double> { … }; template <> class BASE_EXPORT BasicValueConverter<bool> : public ValueConverter<bool> { … }; template <typename FieldType> class ValueFieldConverter : public ValueConverter<FieldType> { … }; template <typename FieldType> class CustomFieldConverter : public ValueConverter<FieldType> { … }; template <typename NestedType> class NestedValueConverter : public ValueConverter<NestedType> { … }; template <typename Element> class RepeatedValueConverter : public ValueConverter<std::vector<std::unique_ptr<Element>>> { … }; template <typename NestedType> class RepeatedMessageConverter : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { … }; template <typename NestedType> class RepeatedCustomValueConverter : public ValueConverter<std::vector<std::unique_ptr<NestedType>>> { … }; } // namespace internal template <class StructType> class JSONValueConverter { … }; } // namespace base #endif // BASE_JSON_JSON_VALUE_CONVERTER_H_