1 #pragma once 2 3 #include <nlohmann/json.hpp> 4 #include <sdbusplus/message/types.hpp> 5 6 namespace utils 7 { 8 9 inline void from_json(const nlohmann::json& j, 10 sdbusplus::message::object_path& o) 11 { 12 o = j.get<std::string>(); 13 } 14 15 inline void from_json(const nlohmann::json& j, 16 std::vector<sdbusplus::message::object_path>& o) 17 { 18 o.clear(); 19 for (const nlohmann::json& item : j) 20 { 21 o.emplace_back(item.get<std::string>()); 22 } 23 } 24 25 namespace detail 26 { 27 28 template <class T> 29 struct has_utils_from_json 30 { 31 template <class U> 32 static U& ref(); 33 34 template <class U> 35 static std::true_type check( 36 decltype(utils::from_json(ref<const nlohmann::json>(), ref<U>()))*); 37 38 template <class> 39 static std::false_type check(...); 40 41 static constexpr bool value = 42 decltype(check<std::decay_t<T>>(nullptr))::value; 43 }; 44 45 template <class T> 46 constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value; 47 48 } // namespace detail 49 50 template <class, class...> 51 struct LabeledTuple; 52 53 template <class... Args, class... Labels> 54 struct LabeledTuple<std::tuple<Args...>, Labels...> 55 { 56 LabeledTuple() = delete; 57 58 static_assert(sizeof...(Args) == sizeof...(Labels)); 59 60 static nlohmann::json to_json(const std::tuple<Args...>& tuple) 61 { 62 nlohmann::json j; 63 to_json_all(j, tuple, std::make_index_sequence<sizeof...(Args)>()); 64 return j; 65 } 66 67 static std::tuple<Args...> from_json(const nlohmann::json& j) 68 { 69 std::tuple<Args...> value; 70 from_json_all(j, value, std::make_index_sequence<sizeof...(Args)>()); 71 return value; 72 } 73 74 private: 75 template <size_t... Idx> 76 static void to_json_all(nlohmann::json& j, const std::tuple<Args...>& tuple, 77 std::index_sequence<Idx...>) 78 { 79 (to_json_item<Idx>(j, tuple), ...); 80 } 81 82 template <size_t Idx> 83 static void to_json_item(nlohmann::json& j, 84 const std::tuple<Args...>& tuple) 85 { 86 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>; 87 j[Label::str()] = std::get<Idx>(tuple); 88 } 89 90 template <size_t... Idx> 91 static void from_json_all(const nlohmann::json& j, 92 std::tuple<Args...>& value, 93 std::index_sequence<Idx...>) 94 { 95 (from_json_item<Idx>(j, value), ...); 96 } 97 98 template <size_t Idx> 99 static void from_json_item(const nlohmann::json& j, 100 std::tuple<Args...>& value) 101 { 102 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>; 103 using T = std::tuple_element_t<Idx, std::tuple<Args...>>; 104 const nlohmann::json& item = j.at(Label::str()); 105 if constexpr (detail::has_utils_from_json_v<T>) 106 { 107 T& v = std::get<Idx>(value); 108 utils::from_json(item, v); 109 } 110 else 111 { 112 std::get<Idx>(value) = item.get<T>(); 113 } 114 } 115 }; 116 117 } // namespace utils 118