#include #include #include namespace clice::json { using namespace llvm::json; template constexpr inline bool is_array_v = false; template constexpr inline bool is_array_v> = true; template constexpr inline bool is_integral_v = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v; template Object serialize(const T& object) { Object result; for_each(object, [&](llvm::StringRef name, Value& value) { if constexpr(is_array_v) { Array array; for(const auto& element: value) { array.push_back(serialize(element)); } result.try_emplace(name, std::move(array)); } else if constexpr(std::is_constructible_v) { result.try_emplace(name, value); } else { result.try_emplace(name, serialize(value)); } }); return result; } template T deserialize(const Object& object) { T result; for_each(result, [&](llvm::StringRef name, Value& value) { if constexpr(is_array_v) { if(const auto* array = object.getArray(name)) { for(std::size_t i = 0; i < array->size(); ++i) { value[i] = deserialize((*array)[i]); } } } else if constexpr(std::is_same_v) { if(auto boolean = object.getBoolean(name)) { value = *boolean; } } else if constexpr(is_integral_v) { if(auto integer = object.getInteger(name)) { value = *integer; } } else if constexpr(is_integral_v) { if(auto floating = object.getNumber(name)) { value = *floating; } } else if constexpr(std::is_same_v) { if(auto string = object.getString(name)) { value = *string; } } else { if(auto subobject = object.getObject(name)) { value = deserialize(*subobject); } } }); return result; } } // namespace clice::json