Skip to content

Latest commit

 

History

History
186 lines (147 loc) · 4.58 KB

223.md

File metadata and controls

186 lines (147 loc) · 4.58 KB
Info

Example

int main() {
  nlohmann::json json{};
  json["value"] = 42;
  json["array"] = std::array{1, 2, 3};
  std::cout << json.dump(); // prints {"array":[1,2,3],"value":42}
}

https://godbolt.org/z/cfs9Ycsh8

Puzzle

  • Can you implement to_json function which converts a given tuple of named fields into nlohmann::json object?
constexpr auto to_json(const auto&); // TODO

template <class T>
struct named {
  std::string_view name{};
  T value{};
};

int main() {
  using namespace boost::ut;

  "to json"_test = [] {
    "value"_test = [] {
      const auto json = to_json(std::tuple{named{.name = "int", .value = 1}});
      expect(1_i == json["int"].get<int>());
    };

    "array"_test = [] {
      const auto json = to_json(
          std::tuple{named{.name = "array", .value = std::array{1, 2}}});
      expect(std::array{1, 2} == json["array"].get<std::array<int, 2>>());
    };

    "complex"_test = [] {
      const auto json = to_json(std::tuple{
          named{.name = "int", .value = 1},
          named{.name = "double", .value = 2.0},
          named{.name = "array", .value = std::array{1, 2, 3}},
          named{.name = "compound",
                .value = std::tuple{named{.name = "unsigned", .value = 42u}}}});

      expect(1_i == json["int"].get<int>() and
             2._d == json["double"].get<double>() and
             std::array{1, 2, 3} == json["array"].get<std::array<int, 3>>() and
             42_u == json["compound"]["unsigned"].get<unsigned>());
    };
  };
}

https://godbolt.org/z/dfq8KxzKd

Solutions

constexpr auto& to_json(const auto& t) {
  return t;
}

template <typename... Ts>
constexpr auto to_json(const std::tuple<Ts...>& t) {
  return std::apply([] (const auto&... ts) {
    nlohmann::json obj{};
    ((obj[std::string{ts.name}] = to_json(ts.value)), ...);
    return obj;
  }, t);
}

https://godbolt.org/z/TxYT46Pb1

constexpr auto to_json(const auto& value) { return value; }

template <typename... Ts>
constexpr auto to_json(const std::tuple<Ts...>& tuple) {
  nlohmann::json output;
  std::apply(
      [&output](const auto&... args) {
        (..., [&output](const auto& arg) {
          output[std::string{arg.name}] = to_json(arg.value);
        }(args));
      },
      tuple);
  return output;
}

https://godbolt.org/z/Kaq4G7hcK

constexpr auto to_json(const auto& value) -> decltype(auto) {
  return value;
}

template <typename... Ts>
constexpr auto to_json(std::tuple<Ts...> const& tuple) {
    nlohmann::json json{};
    std::apply([&] (auto const&... named) {
        ((json[std::string{named.name}] = to_json(named.value)), ...);
    }, tuple);
    return json;
}

https://godbolt.org/z/v7bson4Tx

constexpr auto to_json(const auto& v) { return v; }
template <class... Ts>
constexpr auto to_json(const std::tuple<Ts...>& t) {
  nlohmann::json o{};
  (..., (o[std::string{std::get<Ts>(t).name}] = to_json(std::get<Ts>(t).value)));
  return o;
}

https://godbolt.org/z/jfn8Esac6

template<class T>
constexpr auto to_json(const T& t) { return t; }

template<class ...T>
constexpr auto to_json(const std::tuple<named<T>...>& tup) {
    nlohmann::json json{};
    [&json, &tup] <auto ...Id> (std::index_sequence<Id...> const&) {
        ( (json[std::string(std::get<Id>(tup).name).c_str()] = to_json( std::get<Id>(tup).value)), ...);
    }(std::make_index_sequence<sizeof...(T)>{});
    return json;
}

https://godbolt.org/z/1hKKeGdzc

constexpr auto to_json( auto const & arg){ return arg; }
template<class T>
constexpr std::tuple<const char*,decltype(to_json(T{}))> to_json( named<T> const & arg)
{
    return {arg.name.data(),to_json(arg.value)};
}
template<class ... T>
constexpr auto to_json(std::tuple< named<T> ... > const & arg)
{
    return std::apply( []( auto const & ...args ){ return nlohmann::json{to_json(args)...}; },arg);
}

https://godbolt.org/z/vcf4361Ta

constexpr auto to_json(const auto & value) {
    return value;
}

template<class ...T> constexpr auto to_json(const std::tuple<named<T>...>& tp) {
    nlohmann::json json{};

    std::apply([&](const auto&... n)
    {
        ((json[std::string{n.name}] = to_json(n.value)), ...);
   }, tp);

    return json;
};

https://godbolt.org/z/9TqE9zr3T