9 #include <nlohmann/json.hpp>
12 #define DD_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.m_##v1;
13 #define DD_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.m_##v1);
17 #define DD_JSON_DECLARE_SERIALIZE_TYPE(Type) \
18 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t); \
19 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t);
21 #define DD_JSON_DEFINE_SERIALIZE_STRUCT(Type, ...) \
22 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
23 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_TO, __VA_ARGS__)) \
26 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
27 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(DD_JSON_FROM, __VA_ARGS__)) \
33 #define DD_JSON_DEFINE_SERIALIZE_ENUM_GCOVR_EXCL_BR_LINE(Type, ...) \
34 const std::map<Type, nlohmann::json> & \
35 getEnumMap(const Type &) { \
36 static_assert(std::is_enum<Type>::value, #Type " must be an enum!"); \
37 static const std::map<Type, nlohmann::json> map = __VA_ARGS__; \
41 void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
42 nlohmann_json_j = findInEnumMap<Type>(#Type " is missing enum mapping!", [nlohmann_json_t](const auto &pair) { \
43 return pair.first == nlohmann_json_t; \
47 void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
48 nlohmann_json_t = findInEnumMap<Type>(#Type " is missing enum mapping!", [&nlohmann_json_j](const auto &pair) { \
49 return pair.second == nlohmann_json_j; \
53namespace display_device {
62 struct JsonTypeName<double> {
63 static constexpr std::string_view m_name {
"double"};
67 struct JsonTypeName<Rational> {
68 static constexpr std::string_view m_name {
"rational"};
71 template<
class T,
class... Ts>
72 bool variantFromJson(
const nlohmann::json &nlohmann_json_j, std::variant<Ts...> &value) {
73 if (nlohmann_json_j.at(
"type").get<std::string_view>() != JsonTypeName<T>::m_name) {
77 value = nlohmann_json_j.at(
"value").get<T>();
83 template<
class T,
class Predicate>
84 typename std::map<T, nlohmann::json>::const_iterator findInEnumMap(
const char *error_msg, Predicate predicate) {
85 const auto &map {getEnumMap(T {})};
86 auto it {std::find_if(std::begin(map), std::end(map), predicate)};
87 if (it == std::end(map)) {
88 throw std::runtime_error(error_msg);
97 struct adl_serializer<std::optional<T>> {
98 static void to_json(json &nlohmann_json_j,
const std::optional<T> &nlohmann_json_t) {
99 if (nlohmann_json_t == std::nullopt) {
100 nlohmann_json_j =
nullptr;
102 nlohmann_json_j = *nlohmann_json_t;
106 static void from_json(
const json &nlohmann_json_j, std::optional<T> &nlohmann_json_t) {
107 if (nlohmann_json_j.is_null()) {
108 nlohmann_json_t = std::nullopt;
110 nlohmann_json_t = nlohmann_json_j.get<T>();
117 template<
typename... Ts>
118 struct adl_serializer<std::variant<Ts...>> {
119 static void to_json(json &nlohmann_json_j,
const std::variant<Ts...> &nlohmann_json_t) {
121 [&nlohmann_json_j]<
class T>(
const T &value) {
122 nlohmann_json_j[
"type"] = display_device::detail::JsonTypeName<std::decay_t<T>>::m_name;
123 nlohmann_json_j[
"value"] = value;
129 static void from_json(
const json &nlohmann_json_j, std::variant<Ts...> &nlohmann_json_t) {
131 const bool found {(display_device::detail::variantFromJson<Ts>(nlohmann_json_j, nlohmann_json_t) || ...)};
133 const std::string error {
"Could not parse variant from type " + nlohmann_json_j.at(
"type").get<std::string>() +
"!"};
134 throw std::runtime_error(error);
140 template<
class Rep,
class Period>
141 struct adl_serializer<std::chrono::duration<Rep, Period>> {
142 using NanoRep =
decltype(std::chrono::nanoseconds {}.count());
143 static_assert(std::numeric_limits<Rep>::max() <= std::numeric_limits<NanoRep>::max(),
"Duration support above nanoseconds have not been tested/verified yet!");
145 static void to_json(json &nlohmann_json_j,
const std::chrono::duration<Rep, Period> &nlohmann_json_t) {
146 nlohmann_json_j = nlohmann_json_t.count();
149 static void from_json(
const json &nlohmann_json_j, std::chrono::duration<Rep, Period> &nlohmann_json_t) {
150 nlohmann_json_t = std::chrono::duration<Rep, Period> {nlohmann_json_j.get<Rep>()};