Skip to content

Latest commit

 

History

History
265 lines (212 loc) · 6.81 KB

224.md

File metadata and controls

265 lines (212 loc) · 6.81 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}
  }

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

https://godbolt.org/z/E8sMcPTM8

Puzzle

  • Can you extend to_json function from the last week with support of insertion_order/alphabetical_order policies?
template<class TPolicy = class insertion_order>
constexpr auto to_json(const auto& input); // TODO

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

int main() {
  using namespace boost::ut;
  using std::literals::string_literals::operator""s;

  "to json"_test = [] {
    const auto t = 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}}}};

    "default order"_test = [=] {
      const auto json = to_json(t);
      expect(R"({"int":1,"double":2.0,"array":[1,2,3],"compound":{"unsigned":42}})"s == json.dump());
    };

    "insertion order"_test = [=] {
      const auto json = to_json<class insertion_order>(t);
      expect(R"({"int":1,"double":2.0,"array":[1,2,3],"compound":{"unsigned":42}})"s == json.dump());
    };

    "alphabetical order"_test = [=] {
      const auto json = to_json<class alphabetical_order>(t);
      expect(R"({"array":[1,2,3],"compound":{"unsigned":42},"double":2.0,"int":1})"s == json.dump());
    };
  };
}

https://godbolt.org/z/4jT5fqnvr

Solutions

struct insertion_order {
  using json_t = nlohmann::ordered_json;
};

struct alphabetical_order {
  using json_t = nlohmann::json;
};

using default_order = insertion_order;

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

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

https://godbolt.org/z/5o1KEY6oW

struct alphabetical_order {
    using json_type = nlohmann::json;
};

struct insertion_order {
    using json_type = nlohmann::ordered_json;
};

template <typename TPolicy = insertion_order>
constexpr auto to_json(auto const& value) -> decltype(auto) {
    return value;
}

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

https://godbolt.org/z/j3sPjvceY

struct alphabetical_order {
    using json_type = nlohmann::json;
};

struct insertion_order {
    using json_type = nlohmann::ordered_json;
};

template <typename TPolicy = insertion_order>
constexpr auto to_json(auto const& value) -> decltype(auto) {
    return value;
}

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

https://godbolt.org/z/qsTj8Gf8P

class insertion_order;
class alphabetical_order;

template<class T>
using json_t = typename std::conditional_t<
  std::is_same_v<T, insertion_order>,
    std::type_identity<nlohmann::ordered_json>,
    std::enable_if<
      std::is_same_v<T, alphabetical_order>,
      nlohmann::json>>::type;

template<class TPolicy = class insertion_order, class... Ts>
constexpr auto to_json(const std::tuple<named<Ts>...>& t) {
  return std::apply([] (const auto&... ts) {
    json_t<TPolicy> json{};
    (..., (json[std::string{ts.name}] = to_json<TPolicy>(ts.value)));
    return json;
  }, t);
}

https://godbolt.org/z/s4ov3M9fs

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

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

https://godbolt.org/z/Ee4qa5xTq

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

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

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

    return json;
};

template<class ...T> constexpr auto to_alphabetical_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;
};


template<class TPolicy = insertion_order>
constexpr auto to_json(const auto& input)
{
    if constexpr(std::is_same_v<TPolicy, insertion_order>) {
        return to_json(input);
    }
    else if constexpr(std::is_same_v<TPolicy, alphabetical_order>) {
        return to_alphabetical_json(input);
    }
};

https://godbolt.org/z/hMzeT9nPG

template<class TPolicy = class insertion_order>
constexpr auto to_json( auto const & arg){ return arg; }
template<class TPolicy = class insertion_order,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 TPolicy = class insertion_order,class ... T>
constexpr auto to_json(std::tuple< named<T> ... > const & arg)
{
    if constexpr ( std::is_same_v<TPolicy,class insertion_order> )
        return std::apply( []( auto const & ...args ){ return nlohmann::ordered_json{to_json(args)...}; },arg);
    else
        return std::apply( []( auto const & ...args ){ return nlohmann::json{to_json(args)...}; },arg);
}

https://godbolt.org/z/edzK6drj3