6#include <userver/formats/json/value.hpp>
7#include <userver/formats/parse/to.hpp>
8#include <userver/formats/serialize/to.hpp>
9#include <userver/utils/constexpr_indices.hpp>
10#include <userver/utils/overloaded.hpp>
11#include <userver/utils/trivial_map.hpp>
13USERVER_NAMESPACE_BEGIN
17template <
typename BuilderFunc>
19 std::string_view property_name;
20 utils::TrivialSet<BuilderFunc> mapping;
23template <
typename BuilderFunc>
24OneOfSettings(
const char*,
utils::TrivialSet<BuilderFunc>) ->
OneOfSettings<BuilderFunc>;
26template <
const auto* Settings,
typename... T>
28 const std::variant<formats::common::ParseType<formats::json::Value, T>...>& value;
31template <
const auto* Settings,
typename... T,
typename Value>
32std::variant<formats::common::ParseType<Value, T>...>
33Parse(Value value, formats::parse::To<OneOfWithDiscriminator<Settings, T...>>) {
34 const auto field = value[Settings->property_name].
template As<std::string>();
36 const auto index = Settings->mapping.GetIndex(field);
37 if (!index.has_value()) {
41 using Result = std::variant<formats::common::ParseType<formats::json::Value, T>...>;
44 utils::WithConstexprIndex<
sizeof...(T)>(index.value(), [&](
auto index_constant) {
45 constexpr auto kIndex =
decltype(index_constant)::value;
46 result.
template emplace<kIndex>(value.
template As<std::variant_alternative_t<kIndex, Result>>());
51template <
const auto* Settings,
typename... T,
typename Value>
52Value Serialize(
const OneOfWithDiscriminator<Settings, T...>& var, formats::
serialize::
To<Value>) {
54 USERVER_NAMESPACE::utils::Overloaded{[](
const formats::common::ParseType<Value, T>& item) {
55 return typename Value::Builder(T{item}).ExtractValue();