-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy path224.md
265 lines (212 loc) · 6.81 KB
/
224.md
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
<details open><summary>Info</summary><p>
* **Did you know that the JSON standard does not specify that the insertion order of object elements should be preserved?**
* https://tools.ietf.org/html/rfc8259.html
</p></details><details open><summary>Example</summary><p>
```cpp
int main() {
{
nlohmann::json json{};
json["value"] = 42;
json["array"] = std::array{1, 2, 3};
std::cout << json.dump(); // prints {"array":[1,2,3],"value":42}
}
{
nlohmann::ordered_json json{};
json["value"] = 42;
json["array"] = std::array{1, 2, 3};
std::cout << json.dump(); // prints {"value":42", array":[1,2,3]}
}
}
```
> https://godbolt.org/z/E8sMcPTM8
</p></details><details open><summary>Puzzle</summary><p>
* **Can you extend `to_json` function from the last week with support of insertion_order/alphabetical_order policies?**
```cpp
template<class TPolicy = class insertion_order>
constexpr auto to_json(const auto& input); // TODO
template <class T>
struct named {
std::string_view name{};
T value{};
};
int main() {
using namespace boost::ut;
using std::literals::string_literals::operator""s;
"to json"_test = [] {
const auto t = std::tuple{
named{.name = "int", .value = 1},
named{.name = "double", .value = 2.0},
named{.name = "array", .value = std::array{1, 2, 3}},
named{.name = "compound",
.value = std::tuple{named{.name = "unsigned", .value = 42u}}}};
"default order"_test = [=] {
const auto json = to_json(t);
expect(R"({"int":1,"double":2.0,"array":[1,2,3],"compound":{"unsigned":42}})"s == json.dump());
};
"insertion order"_test = [=] {
const auto json = to_json<class insertion_order>(t);
expect(R"({"int":1,"double":2.0,"array":[1,2,3],"compound":{"unsigned":42}})"s == json.dump());
};
"alphabetical order"_test = [=] {
const auto json = to_json<class alphabetical_order>(t);
expect(R"({"array":[1,2,3],"compound":{"unsigned":42},"double":2.0,"int":1})"s == json.dump());
};
};
}
```
> https://godbolt.org/z/4jT5fqnvr
</p></details><details><summary>Solutions</summary><p>
```cpp
struct insertion_order {
using json_t = nlohmann::ordered_json;
};
struct alphabetical_order {
using json_t = nlohmann::json;
};
using default_order = insertion_order;
template <class TPolicy = default_order>
constexpr auto& to_json(const auto& t) {
return t;
}
template <class TPolicy = default_order, typename... Ts>
constexpr auto to_json(const std::tuple<Ts...>& t) {
return std::apply([] (const auto&... ts) {
typename TPolicy::json_t obj{};
((obj[std::string{ts.name}] = to_json<TPolicy>(ts.value)), ...);
return obj;
}, t);
}
```
> https://godbolt.org/z/5o1KEY6oW
```cpp
struct alphabetical_order {
using json_type = nlohmann::json;
};
struct insertion_order {
using json_type = nlohmann::ordered_json;
};
template <typename TPolicy = insertion_order>
constexpr auto to_json(auto const& value) -> decltype(auto) {
return value;
}
template <typename TPolicy = insertion_order, typename... Ts>
constexpr auto to_json(std::tuple<Ts...> const& tuple) {
typename TPolicy::json_type json{};
std::apply([&] (auto const&... named) {
((json[std::string{named.name}] = to_json<TPolicy>(named.value)), ...);
}, tuple);
return json;
}
```
> https://godbolt.org/z/j3sPjvceY
```cpp
struct alphabetical_order {
using json_type = nlohmann::json;
};
struct insertion_order {
using json_type = nlohmann::ordered_json;
};
template <typename TPolicy = insertion_order>
constexpr auto to_json(auto const& value) -> decltype(auto) {
return value;
}
template <typename TPolicy = insertion_order, typename... Ts>
constexpr auto to_json(std::tuple<Ts...> const& tuple) {
typename TPolicy::json_type json{};
std::apply([&] (auto const&... named) {
((json[std::string{named.name}] = to_json<TPolicy>(named.value)), ...);
}, tuple);
return json;
}
```
> https://godbolt.org/z/qsTj8Gf8P
```cpp
class insertion_order;
class alphabetical_order;
template<class T>
using json_t = typename std::conditional_t<
std::is_same_v<T, insertion_order>,
std::type_identity<nlohmann::ordered_json>,
std::enable_if<
std::is_same_v<T, alphabetical_order>,
nlohmann::json>>::type;
template<class TPolicy = class insertion_order, class... Ts>
constexpr auto to_json(const std::tuple<named<Ts>...>& t) {
return std::apply([] (const auto&... ts) {
json_t<TPolicy> json{};
(..., (json[std::string{ts.name}] = to_json<TPolicy>(ts.value)));
return json;
}, t);
}
```
> https://godbolt.org/z/s4ov3M9fs
```cpp
constexpr auto& to_json(const auto& t) {
return t;
}
template <class TPolicy = class insertion_order, typename... Ts>
constexpr auto to_json(const std::tuple<Ts...>& t) {
return std::apply([] (const auto&... ts) {
if constexpr( std::is_same_v<TPolicy, class insertion_order> ) {
nlohmann::ordered_json obj{};
((obj[std::string{ts.name}] = to_json(ts.value)), ...);
return obj;
} else {
nlohmann::json obj{};
((obj[std::string{ts.name}] = to_json(ts.value)), ...);
return obj;
}
}, t);
}
```
> https://godbolt.org/z/Ee4qa5xTq
```cpp
constexpr auto to_json(const auto & value) {
return value;
}
template<class ...T> constexpr auto to_json(const std::tuple<named<T>...>& tp) {
nlohmann::ordered_json json{};
std::apply([&](const auto&... n)
{
((json[std::string{n.name}] = to_json(n.value)), ...);
}, tp);
return json;
};
template<class ...T> constexpr auto to_alphabetical_json(const std::tuple<named<T>...>& tp) {
nlohmann::json json{};
std::apply([&](const auto&... n)
{
((json[std::string{n.name}] = to_json(n.value)), ...);
}, tp);
return json;
};
template<class TPolicy = insertion_order>
constexpr auto to_json(const auto& input)
{
if constexpr(std::is_same_v<TPolicy, insertion_order>) {
return to_json(input);
}
else if constexpr(std::is_same_v<TPolicy, alphabetical_order>) {
return to_alphabetical_json(input);
}
};
```
> https://godbolt.org/z/hMzeT9nPG
```cpp
template<class TPolicy = class insertion_order>
constexpr auto to_json( auto const & arg){ return arg; }
template<class TPolicy = class insertion_order,class T>
constexpr std::tuple<const char*,decltype(to_json(T{}))> to_json( named<T> const & arg)
{
return {arg.name.data(),to_json(arg.value)};
}
template<class TPolicy = class insertion_order,class ... T>
constexpr auto to_json(std::tuple< named<T> ... > const & arg)
{
if constexpr ( std::is_same_v<TPolicy,class insertion_order> )
return std::apply( []( auto const & ...args ){ return nlohmann::ordered_json{to_json(args)...}; },arg);
else
return std::apply( []( auto const & ...args ){ return nlohmann::json{to_json(args)...}; },arg);
}
```
> https://godbolt.org/z/edzK6drj3