chromium/base/json/json_value_converter.h

// 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_