10 #include <nlohmann/json.hpp>
14 #define DD_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.m_##v1;
15 #define DD_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.m_##v1);
19 #define DD_JSON_DECLARE_SERIALIZE_TYPE(Type) \
20 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t); \
21 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t);
23 #define DD_JSON_DEFINE_SERIALIZE_STRUCT(Type, ...) \
24 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
25 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_TO, __VA_ARGS__)) \
28 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
29 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_FROM, __VA_ARGS__)) \
35 #define DD_JSON_DEFINE_SERIALIZE_ENUM_GCOVR_EXCL_BR_LINE(Type, ...) \
36 const std::map<Type, nlohmann::json> & \
37 getEnumMap(const Type &) { \
38 static_assert(std::is_enum<Type>::value, #Type " must be an enum!"); \
39 static const std::map<Type, nlohmann::json> map = __VA_ARGS__; \
43 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
44 nlohmann_json_j = findInEnumMap<Type>(#Type " is missing enum mapping!", [nlohmann_json_t](const auto &pair) { \
45 return pair.first == nlohmann_json_t; \
49 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
50 nlohmann_json_t = findInEnumMap<Type>(#Type " is missing enum mapping!", [&nlohmann_json_j](const auto &pair) { \
51 return pair.second == nlohmann_json_j; \
55namespace display_device {
64 struct JsonTypeName<double> {
65 static constexpr std::string_view m_name {
"double"};
69 struct JsonTypeName<Rational> {
70 static constexpr std::string_view m_name {
"rational"};
73 template<
class T,
class... Ts>
74 bool variantFromJson(
const nlohmann::json &nlohmann_json_j, std::variant<Ts...> &value) {
75 if (nlohmann_json_j.at(
"type").get<std::string_view>() != JsonTypeName<T>::m_name) {
79 value = nlohmann_json_j.at(
"value").get<T>();
85 template<
class T,
class Predicate>
86 typename std::map<T, nlohmann::json>::const_iterator findInEnumMap(
const char *error_msg, Predicate predicate) {
87 const auto &map {getEnumMap(T {})};
88 auto it {std::ranges::find_if(map, predicate)};
89 if (it == std::end(map)) {
90 throw std::out_of_range(error_msg);
99 struct adl_serializer<std::optional<T>> {
100 static void to_json(json &nlohmann_json_j,
const std::optional<T> &nlohmann_json_t) {
101 if (nlohmann_json_t == std::nullopt) {
102 nlohmann_json_j =
nullptr;
104 nlohmann_json_j = *nlohmann_json_t;
108 static void from_json(
const json &nlohmann_json_j, std::optional<T> &nlohmann_json_t) {
109 if (nlohmann_json_j.is_null()) {
110 nlohmann_json_t = std::nullopt;
112 nlohmann_json_t = nlohmann_json_j.get<T>();
119 template<
typename... Ts>
120 struct adl_serializer<std::variant<Ts...>> {
121 static void to_json(json &nlohmann_json_j,
const std::variant<Ts...> &nlohmann_json_t) {
123 [&nlohmann_json_j]<
class T>(
const T &value) {
124 nlohmann_json_j[
"type"] = display_device::detail::JsonTypeName<std::decay_t<T>>::m_name;
125 nlohmann_json_j[
"value"] = value;
131 static void from_json(
const json &nlohmann_json_j, std::variant<Ts...> &nlohmann_json_t) {
133 const bool found {(display_device::detail::variantFromJson<Ts>(nlohmann_json_j, nlohmann_json_t) || ...)};
135 const std::string error {
"Could not parse variant from type " + nlohmann_json_j.at(
"type").get<std::string>() +
"!"};
136 throw std::invalid_argument(error);
142 template<
class Rep,
class Period>
143 struct adl_serializer<std::chrono::duration<Rep, Period>> {
144 using NanoRep =
decltype(std::chrono::nanoseconds {}.count());
145 static_assert(std::numeric_limits<Rep>::max() <= std::numeric_limits<NanoRep>::max(),
"Duration support above nanoseconds have not been tested/verified yet!");
147 static void to_json(json &nlohmann_json_j,
const std::chrono::duration<Rep, Period> &nlohmann_json_t) {
148 nlohmann_json_j = nlohmann_json_t.count();
151 static void from_json(
const json &nlohmann_json_j, std::chrono::duration<Rep, Period> &nlohmann_json_t) {
152 nlohmann_json_t = std::chrono::duration<Rep, Period> {nlohmann_json_j.get<Rep>()};