Skip to content

Commit

Permalink
Refactors of json util functions (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
IESE-T3 authored Jul 17, 2024
1 parent e67ce06 commit 049a475
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 108 deletions.
4 changes: 2 additions & 2 deletions include/DRAMUtils/memspec/MemSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@

#include <string>
#include <variant>
#include "DRAMUtils/util/json.h"
#include "nlohmann/json.hpp"
#include <iostream>

#include "DRAMUtils/util/json.h"
#include "DRAMUtils/util/types.h"
#include "DRAMUtils/util/id_variant.h"

Expand Down
127 changes: 124 additions & 3 deletions include/DRAMUtils/util/id_variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
#include <variant>
#include <string_view>
#include <utility>
#include "types.h"
#include "nlohmann/json.hpp"

#include <DRAMUtils/util/json.h>
#include <DRAMUtils/util/types.h>

#define DRAMUTILS_DECLARE_IDVARIANT(VariantName, IDFieldName, VariantTypeSequence) \
namespace detail { \
struct id_field_name_##VariantName { static constexpr char name[] = IDFieldName; }; \
Expand Down Expand Up @@ -71,7 +73,7 @@ class IdVariant<id_field_name, util::type_sequence<Ts...>>

using VariantTypes = util::type_sequence<Ts...>;
using Variant = util::type_sequence_id_variant_t<VariantTypes>;
using Json = nlohmann::json;
using Json = ::json_t;
Variant variant;

private:
Expand Down Expand Up @@ -116,6 +118,125 @@ class IdVariant<id_field_name, util::type_sequence<Ts...>>
}
};


// Json helper functions

template <const char* id_field_name, typename Seq>
void id_variant_from_json(const nlohmann::json& j, IdVariant<id_field_name, Seq>& data, std::optional<std::string_view> key)
{
if (key)
{
// Find key
const auto it = j.find(*key);
if (it != j.end())
{
// Key in json
if (!data.from_json(j[*key]))
throw std::bad_variant_access{};
}
else
{
// Key not in json
throw std::bad_variant_access{};
}
}
else {
// No key
if (!data.from_json(j))
throw std::bad_variant_access{};
}
}

template <const char* id_field_name, typename Seq>
void id_variant_to_json(nlohmann::json& j, const IdVariant<id_field_name, Seq>& data, std::optional<std::string_view> key)
{
if (key)
data.to_json(j[*key]);
else
data.to_json(j);

}


template <typename>
constexpr bool is_id_variant = false;
template <char const * id_field_name, typename Seq>
constexpr bool is_id_variant<IdVariant<id_field_name, Seq>> = true;


template <typename T> void extended_to_json(const char* key, nlohmann::json& j, const T& value)
{
if constexpr (is_optional<T>)
optional_to_json(j, value, key);
else if constexpr (is_id_variant<T>)
id_variant_to_json(j, value, key);
else if constexpr (is_variant<T>)
variant_to_json(j, value);
else
j[key] = value;
}

template <typename T> void extended_from_json(const char* key, const nlohmann::json& j, T& value)
{
if constexpr (is_optional<T>)
optional_from_json(j, value, key);
else if constexpr (is_id_variant<T>)
id_variant_from_json(j, value, key);
else if constexpr (is_variant<T>)
variant_from_json<T>(j, value);
else
j.at(key).get_to(value);
}


} // namespace DRAMUtils::util



NLOHMANN_JSON_NAMESPACE_BEGIN

template <typename... Ts> struct adl_serializer<std::variant<Ts...>>
{
static void to_json(nlohmann::json& j, const std::variant<Ts...>& data)
{
DRAMUtils::util::variant_to_json<Ts...>(j, data);
}

static void from_json(const nlohmann::json& j, std::variant<Ts...>& data)
{
// Call variant_from_json for all types, only one will succeed
(DRAMUtils::util::variant_from_json<Ts>(j, data), ...);
}
};


template <const char * id_field_name, typename Seq> struct adl_serializer<DRAMUtils::util::IdVariant<id_field_name, Seq>>
{
static void to_json(nlohmann::json& j, const DRAMUtils::util::IdVariant<id_field_name, Seq>& data)
{
DRAMUtils::util::id_variant_to_json<id_field_name, Seq>(j, data, std::nullopt);
}

static void from_json(const nlohmann::json& j, DRAMUtils::util::IdVariant<id_field_name, Seq>& data)
{
// Match variant by id
DRAMUtils::util::id_variant_from_json<id_field_name, Seq>(j, data, std::nullopt);
}
};


NLOHMANN_JSON_NAMESPACE_END

// NOLINTBEGIN(cppcoreguidelines-macro-usage)

#define EXTEND_JSON_TO(v1) \
DRAMUtils::util::extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
#define EXTEND_JSON_FROM(v1) \
DRAMUtils::util::extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);

// NOLINTEND(cppcoreguidelines-macro-usage)




#endif /* DRAMUTILS_UTIL_ID_VARIANT_H */
105 changes: 2 additions & 103 deletions include/DRAMUtils/util/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#include <optional>
#include <variant>
#include <string>
#include "id_variant.h"

using json_t = nlohmann::json;

Expand All @@ -69,41 +68,6 @@ void variant_to_json(nlohmann::json& j, const std::variant<Ts...> &data)
std::visit([&j](const auto& v) { j = v; }, data);
}

template <const char* id_field_name, typename Seq>
void id_variant_from_json(const nlohmann::json& j, IdVariant<id_field_name, Seq>& data, std::optional<std::string_view> key)
{
if (key)
{
// Find key
const auto it = j.find(*key);
if (it != j.end())
{
// Key in json
if (!data.from_json(j[*key]))
throw std::bad_variant_access{};
}
else
{
// Key not in json
throw std::bad_variant_access{};
}
}
else {
// No key
if (!data.from_json(j))
throw std::bad_variant_access{};
}
}

template <const char* id_field_name, typename Seq>
void id_variant_to_json(nlohmann::json& j, const IdVariant<id_field_name, Seq>& data, std::optional<std::string_view> key)
{
if (key)
data.to_json(j[*key]);
else
data.to_json(j);

}

template <typename T>
void optional_to_json(nlohmann::json& j, const std::optional<T>& data, std::optional<std::string_view> key)
Expand Down Expand Up @@ -137,73 +101,15 @@ constexpr bool is_optional = false;
template <typename T>
constexpr bool is_optional<std::optional<T>> = true;

template <typename>
constexpr bool is_id_variant = false;
template <char const * id_field_name, typename Seq>
constexpr bool is_id_variant<IdVariant<id_field_name, Seq>> = true;

template <typename>
constexpr bool is_variant = false;
template <typename... Ts>
constexpr bool is_variant<std::variant<Ts...>> = true;

template <typename T> void extended_to_json(const char* key, nlohmann::json& j, const T& value)
{
if constexpr (is_optional<T>)
optional_to_json(j, value, key);
else if constexpr (is_id_variant<T>)
id_variant_to_json(j, value, key);
else if constexpr (is_variant<T>)
variant_to_json(j, value);
else
j[key] = value;
}

template <typename T> void extended_from_json(const char* key, const nlohmann::json& j, T& value)
{
if constexpr (is_optional<T>)
optional_from_json(j, value, key);
else if constexpr (is_id_variant<T>)
id_variant_from_json(j, value, key);
else if constexpr (is_variant<T>)
variant_from_json<T>(j, value);
else
j.at(key).get_to(value);
}

} // namespace DRAMUtils::util

NLOHMANN_JSON_NAMESPACE_BEGIN

template <typename... Ts> struct adl_serializer<std::variant<Ts...>>
{
static void to_json(nlohmann::json& j, const std::variant<Ts...>& data)
{
DRAMUtils::util::variant_to_json<Ts...>(j, data);
}

static void from_json(const nlohmann::json& j, std::variant<Ts...>& data)
{
// Call variant_from_json for all types, only one will succeed
(DRAMUtils::util::variant_from_json<Ts>(j, data), ...);
}
};


template <const char * id_field_name, typename Seq> struct adl_serializer<DRAMUtils::util::IdVariant<id_field_name, Seq>>
{
static void to_json(nlohmann::json& j, const DRAMUtils::util::IdVariant<id_field_name, Seq>& data)
{
DRAMUtils::util::id_variant_to_json<id_field_name, Seq>(j, data, std::nullopt);
}

static void from_json(const nlohmann::json& j, DRAMUtils::util::IdVariant<id_field_name, Seq>& data)
{
// Match variant by id
DRAMUtils::util::id_variant_from_json<id_field_name, Seq>(j, data, std::nullopt);
}
};

template <typename T> struct adl_serializer<std::optional<T>>
{
static void to_json(json_t& j, const std::optional<T>& opt)
Expand Down Expand Up @@ -231,14 +137,6 @@ template <typename T> struct adl_serializer<std::optional<T>>
}
};

NLOHMANN_JSON_NAMESPACE_END

// NOLINTBEGIN(cppcoreguidelines-macro-usage)

#define EXTEND_JSON_TO(v1) \
DRAMUtils::util::extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
#define EXTEND_JSON_FROM(v1) \
DRAMUtils::util::extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);

#define NLOHMANN_JSONIFY_ALL_THINGS(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \
Expand All @@ -250,6 +148,7 @@ NLOHMANN_JSON_NAMESPACE_END
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, __VA_ARGS__)) \
}

// NOLINTEND(cppcoreguidelines-macro-usage)

NLOHMANN_JSON_NAMESPACE_END

#endif /* DRAMUTILS_UTIL_JSON_H */

0 comments on commit 049a475

Please sign in to comment.