-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathjson_serializer.hpp
127 lines (120 loc) · 3.43 KB
/
json_serializer.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once
#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>
#include <format>
#include <fstream>
#include <ranges>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
class JsonSerializer
{
public:
JsonSerializer(std::string path, nlohmann::json js = nlohmann::json()) :
mfaConfPath(path), jsonData(std::move(js))
{}
inline auto stringSplitter()
{
return std::views::split('/') | std::views::transform([](auto&& sub) {
return std::string(sub.begin(), sub.end());
});
}
nlohmann::json makeJson(const std::string& key, const std::string& value)
{
auto keys = key | stringSplitter();
std::vector v(keys.begin(), keys.end());
auto rv = v | std::views::reverse;
nlohmann::json init;
init[rv.front()] = value;
auto newJson = std::reduce(rv.begin() + 1, rv.end(), init,
[](auto sofar, auto currentKey) {
nlohmann::json j;
j[currentKey] = sofar;
return j;
});
return newJson;
}
std::optional<nlohmann::json> getLeafNode(const std::string_view keyPath)
{
auto keys = keyPath | stringSplitter();
nlohmann::json current = jsonData;
for (auto key : keys)
{
if (!current.contains(key))
{
return std::nullopt;
}
current = current[key];
}
return current;
}
void serialize(std::string key, const std::string value)
{
jsonData.merge_patch(makeJson(key, value));
}
template <typename T>
void deserialize(std::string key, T& value)
{
auto leaf = getLeafNode(key);
if (leaf)
{
value = *leaf;
}
}
void erase(std::string key)
{
if (jsonData.contains(key))
{
jsonData.erase(key);
}
}
bool store()
{
std::filesystem::path dir =
std::filesystem::path(mfaConfPath).parent_path();
// Check if the directory exists, and create it if it does not
if (!dir.string().empty() && !std::filesystem::exists(dir))
{
std::error_code ec;
if (!std::filesystem::create_directories(dir, ec))
{
lg2::error("Unable to create directory {DIR}", "DIR",
dir.string());
return false;
}
}
std::ofstream file(mfaConfPath.data());
if (file.is_open())
{
file << jsonData.dump(4); // Pretty print with 4 spaces
file.close();
return true;
}
else
{
lg2::error("Unable to open file {FILENAME}", "FILENAME",
mfaConfPath);
return false;
}
}
void load()
{
std::ifstream file(mfaConfPath.data());
if (file.is_open())
{
file >> jsonData;
file.close();
}
else
{
lg2::error("Unable to open file for reading {FILENAME}", "FILENAME",
mfaConfPath);
}
}
private:
const std::string mfaConfPath;
nlohmann::json jsonData;
};