-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsonbind.hpp
More file actions
343 lines (318 loc) · 11.6 KB
/
jsonbind.hpp
File metadata and controls
343 lines (318 loc) · 11.6 KB
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#ifndef INCLUDE_JSONBIND_HPP_
#define INCLUDE_JSONBIND_HPP_
// by git@github.com:yuwf/jsonbind.git
// 将结构与nlohmann::json绑定,结构和json可以相互转换
// https://github.com/nlohmann/json
#include <json.hpp>
using json = nlohmann::json;
/* 使用案例
struct Student
{
struct Pen
{
std::string name;
std::string count;
JSON_BIND((name)(count)); // 绑定结构字段和json
};
struct HomeWork
{
std::string name;
std::vector<int> finish;
JSON_BIND_MAP(("n", name)("f", finish)); // json中n对应name字段 此种方式可以缩小key的大小
};
std::string name;
int age = 0;
std::vector<Pen> pens;
std::map<std::string, HomeWork> homeworks;
JSON_BIND((name)(age)(homeworks)(pens)); // 绑定结构字段和json
};
Student student;
// 结构和json格式相互转化
json j;
student.to_json(j);
student.from_json(j);
// 结构和json格式的string相互转化
std::string str;
student.to_string(str);
student.from_string(str);
student.from_buff(str.data(), str.size());
// 结构和msgpack格式相互转化 经测试对比性能要比msgpack官方提供的包慢4倍 json这个库的性能并不是最优的,但使用是比较便捷
std::vector<char> msgpack;
student.to_msgpack(msgpack);
student.from_msgpack(msgpack.data(), msgpack.size());
*/
// 自定义类型支持嵌套时,json内部调用转化成json
namespace nlohmann
{
// 支持结构和json转化
template <typename T>
struct adl_serializer<T, typename std::enable_if<T::JSON_BIND_SUPPORT>::type>
{
static void to_json(json& j, const T& o)
{
o.to_json(j);
}
static void from_json(const json& j, T& o)
{
if (!j.is_object())
{
throw detail::type_error::create(302, std::string("type must be object[") + typeid(T).name() + "], but is " + std::string(j.type_name()), j);
}
o._from_json(j);
}
};
// std::map的key类型为int时,json内部按数组处理,这里给调整下
template <typename Key, typename Value, typename Compare, typename Allocator>
struct adl_serializer<std::map<Key, Value, Compare, Allocator>, typename std::enable_if<std::is_integral<Key>::value>::type>
{
using T = std::map<Key, Value, Compare, Allocator>;
static void to_json(json& j, const T& o)
{
for (const auto& it : o)
{
j[std::to_string(it.first)] = it.second;
}
}
static void from_json(const json& j, T& o)
{
if (!j.is_object())
{
throw detail::type_error::create(302, std::string("type must be object[") + typeid(T).name() + "], but is " + std::string(j.type_name()), j);
}
const auto* inner_object = j.template get_ptr<const typename json::object_t*>();
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(o, o.begin()),
[](typename json::object_t::value_type const& p)
{
return T::value_type(atoi(p.first.c_str()), p.second.template get<typename T::mapped_type>());
});
}
};
}
#define JSON_BIND_SEQ_FOR(...) JSON_BIND_SEQ_FOR_TAIL(__VA_ARGS__)
#define JSON_BIND_SEQ_FOR_TAIL(...) __VA_ARGS__##0
// seq中取第一个字段形成新的seq
// (first, second)(first, second)(first, second) -> (first)(first)(first)
#define JSON_BIND_SEQFIRST_TO_SEQ_A(first, second) JSON_BIND_SEQFIRST_TO_SEQ_I(first, second) JSON_BIND_SEQFIRST_TO_SEQ_B
#define JSON_BIND_SEQFIRST_TO_SEQ_B(first, second) JSON_BIND_SEQFIRST_TO_SEQ_I(first, second) JSON_BIND_SEQFIRST_TO_SEQ_A
#define JSON_BIND_SEQFIRST_TO_SEQ_A0
#define JSON_BIND_SEQFIRST_TO_SEQ_B0
#define JSON_BIND_SEQFIRST_TO_SEQ_I(first, second) (first)
// seq中取第二个字段形成新的seq
// (first, second)(first, second)(first, second) -> (second)(second)(second)
#define JSON_BIND_SEQSECOND_TO_SEQ_A(first, second) JSON_BIND_SEQSECOND_TO_SEQ_I(first, second) JSON_BIND_SEQSECOND_TO_SEQ_B
#define JSON_BIND_SEQSECOND_TO_SEQ_B(first, second) JSON_BIND_SEQSECOND_TO_SEQ_I(first, second) JSON_BIND_SEQSECOND_TO_SEQ_A
#define JSON_BIND_SEQSECOND_TO_SEQ_A0
#define JSON_BIND_SEQSECOND_TO_SEQ_B0
#define JSON_BIND_SEQSECOND_TO_SEQ_I(first, second) (second)
// seq中取第一个字段形成新的tuple
// (first, second)(first, second)(first, second) -> first,first,first,
#define JSON_BIND_SEQFIRST_TO_TUPLE_A(first, second) JSON_BIND_SEQFIRST_TO_TUPLE_I(first, second) JSON_BIND_SEQFIRST_TO_TUPLE_B
#define JSON_BIND_SEQFIRST_TO_TUPLE_B(first, second) JSON_BIND_SEQFIRST_TO_TUPLE_I(first, second) JSON_BIND_SEQFIRST_TO_TUPLE_A
#define JSON_BIND_SEQFIRST_TO_TUPLE_A0
#define JSON_BIND_SEQFIRST_TO_TUPLE_B0
#define JSON_BIND_SEQFIRST_TO_TUPLE_I(first, second) first,
// seq中取第二个字段形成新的tuple
// (first, second)(first, second)(first, second) -> second,second,second,
#define JSON_BIND_SEQSECOND_TO_TUPLE_A(first, second) JSON_BIND_SEQSECOND_TO_TUPLE_I(first, second) JSON_BIND_SEQSECOND_TO_TUPLE_B
#define JSON_BIND_SEQSECOND_TO_TUPLE_B(first, second) JSON_BIND_SEQSECOND_TO_TUPLE_I(first, second) JSON_BIND_SEQSECOND_TO_TUPLE_A
#define JSON_BIND_SEQSECOND_TO_TUPLE_A0
#define JSON_BIND_SEQSECOND_TO_TUPLE_B0
#define JSON_BIND_SEQSECOND_TO_TUPLE_I(first, second) second,
//seq转化成新的tuple
// (member)(member)(member) -> member,member,member,
#define JSON_BIND_SEQ_TO_TUPLE_A(member) JSON_BIND_SEQ_TO_TUPLE_I(member) JSON_BIND_SEQ_TO_TUPLE_B
#define JSON_BIND_SEQ_TO_TUPLE_B(member) JSON_BIND_SEQ_TO_TUPLE_I(member) JSON_BIND_SEQ_TO_TUPLE_A
#define JSON_BIND_SEQ_TO_TUPLE_A0
#define JSON_BIND_SEQ_TO_TUPLE_B0
#define JSON_BIND_SEQ_TO_TUPLE_I(member) #member,
// seq转化成json
// (member)(member)(member) -> j.emplace(#member, member);j.emplace(#member, member);j.emplace(#member, member);
#define JSON_BIND_SEQ_TO_JSON_A(member) JSON_BIND_SEQ_TO_JSON_I(member) JSON_BIND_SEQ_TO_JSON_B
#define JSON_BIND_SEQ_TO_JSON_B(member) JSON_BIND_SEQ_TO_JSON_I(member) JSON_BIND_SEQ_TO_JSON_A
#define JSON_BIND_SEQ_TO_JSON_A0
#define JSON_BIND_SEQ_TO_JSON_B0
#define JSON_BIND_SEQ_TO_JSON_I(member) j.emplace(#member, member);
//seq转化成json,内部嵌套的是pair结构
// (first, second)(first, second)(first, second) -> j.emplace(first, second);j.emplace(first, second);j.emplace(first, second);
#define JSON_BIND_SEQMAP_TO_JSON_A(first, second) JSON_BIND_SEQMAP_TO_JSON_I(first, second) JSON_BIND_SEQMAP_TO_JSON_B
#define JSON_BIND_SEQMAP_TO_JSON_B(first, second) JSON_BIND_SEQMAP_TO_JSON_I(first, second) JSON_BIND_SEQMAP_TO_JSON_A
#define JSON_BIND_SEQMAP_TO_JSON_A0
#define JSON_BIND_SEQMAP_TO_JSON_B0
#define JSON_BIND_SEQMAP_TO_JSON_I(first, second) j.emplace(first, second);
// json转化成结构
#define JSON_BIND_SEQ_FROM_JSON_A(member) JSON_BIND_SEQ_FROM_JSON_I(member) JSON_BIND_SEQ_FROM_JSON_B
#define JSON_BIND_SEQ_FROM_JSON_B(member) JSON_BIND_SEQ_FROM_JSON_I(member) JSON_BIND_SEQ_FROM_JSON_A
#define JSON_BIND_SEQ_FROM_JSON_A0
#define JSON_BIND_SEQ_FROM_JSON_B0
#define JSON_BIND_SEQ_FROM_JSON_I(member) \
{ \
json::const_iterator it = j.find(#member); \
if (it != j.end() && !it->is_null()) \
{ \
it->get_to(member); \
} \
}
// json转化成结构
#define JSON_BIND_SEQMAP_FROM_JSON_A(first, second) JSON_BIND_SEQMAP_FROM_JSON_I(first, second) JSON_BIND_SEQMAP_FROM_JSON_B
#define JSON_BIND_SEQMAP_FROM_JSON_B(first, second) JSON_BIND_SEQMAP_FROM_JSON_I(first, second) JSON_BIND_SEQMAP_FROM_JSON_A
#define JSON_BIND_SEQMAP_FROM_JSON_A0
#define JSON_BIND_SEQMAP_FROM_JSON_B0
#define JSON_BIND_SEQMAP_FROM_JSON_I(first, second) \
{ \
json::const_iterator it = j.find(first); \
if (it != j.end() && !it->is_null()) \
{ \
it->get_to(second); \
} \
}
// 定义的常用一些函数
#define JSON_BIND_FUNCTION() \
void to_string(std::string& str, int indent = -1) \
{ \
json j; \
to_json(j); \
nlohmann::detail::serializer<json> s(nlohmann::detail::output_adapter<char, std::string>(str), ' ', nlohmann::detail::error_handler_t::replace); \
if (indent >= 0) \
s.dump(*this, true, true, static_cast<unsigned int>(indent)); \
else \
s.dump(*this, false, true, 0); \
} \
bool from_string(const std::string& str, std::string* err = NULL) \
{ \
json j; \
nlohmann::detail::span_input_adapter adapter(str.data(), str.size()); \
auto ia = adapter.get(); \
nlohmann::detail::parser<json, decltype(ia)> parser(std::move(ia), nullptr, true, false); \
try \
{ \
parser.parse(true, j); \
} \
catch (const std::exception& ex) \
{ \
if (err) { *err = ex.what(); } \
return false; \
} \
return from_json(j, err); \
} \
bool from_buff(const char* buff, std::size_t len, std::string* err = NULL) \
{ \
json j; \
nlohmann::detail::span_input_adapter adapter(buff, len); \
auto ia = adapter.get(); \
nlohmann::detail::parser<json, decltype(ia)> parser(std::move(ia), nullptr, true, false); \
try \
{ \
parser.parse(true, j); \
} \
catch (const std::exception& ex) \
{ \
if (err) { *err = ex.what(); } \
return false; \
} \
return from_json(j, err); \
} \
void to_msgpack(std::vector<char>& buff) \
{ \
json j; \
to_json(j); \
nlohmann::detail::output_adapter<char> oa(buff); \
nlohmann::json::to_msgpack(j, oa); \
} \
bool from_msgpack(const char* buff, std::size_t len, std::string* err = NULL) \
{ \
json j; \
nlohmann::detail::json_sax_dom_parser<json> sdp(j, true); \
nlohmann::detail::span_input_adapter adapter(buff, len); \
auto ia = adapter.get(); \
nlohmann::detail::binary_reader<json, decltype(ia)> reader(std::move(ia)); \
try \
{ \
reader.sax_parse(nlohmann::detail::input_format_t::msgpack, &sdp, true); \
} \
catch (const std::exception& ex) \
{ \
if (err) { *err = ex.what();} \
} \
if (sdp.is_errored()) return false;\
return from_json(j, err); \
}
// 参数seq,结构字段
// (member)(member)
// member为结构字段
// _from_json 是给内部使用的 他不包异常,异常一直往上传导
#define JSON_BIND(...) \
enum { JSON_BIND_SUPPORT = 1 };\
static const std::vector<std::string>& json_key() \
{ \
static std::vector<std::string> keys = { JSON_BIND_SEQ_FOR(JSON_BIND_SEQ_TO_TUPLE_A __VA_ARGS__) }; \
return keys; \
} \
void to_json(json& j) const \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQ_TO_JSON_A __VA_ARGS__) \
} \
bool from_json(const json& j, std::string* err = NULL) \
{ \
if (!j.is_object()) \
{ \
if (err) { *err = std::string("type must be object[") + typeid(*this).name() + "], but is " + std::string(j.type_name()); } \
return false; \
} \
try \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQ_FROM_JSON_A __VA_ARGS__) \
return true; \
} \
catch (const std::exception& ex) \
{ \
if (err) { *err = ex.what(); } \
} \
return false; \
} \
void _from_json(const json& j) \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQ_FROM_JSON_A __VA_ARGS__) \
} \
JSON_BIND_FUNCTION();
// 参数seq结构,内部嵌套的是pair结构
// (first, second)(first, second)
// first为std::string的类型或可以隐世转出std::string类型
// second为结构字段
// _from_json 是给内部使用的 他不包异常,异常一直往上传导
#define JSON_BIND_MAP(...) \
enum { JSON_BIND_SUPPORT = 1 };\
static const std::vector<std::string>& json_key() \
{ \
static std::vector<std::string> keys = { JSON_BIND_SEQ_FOR(JSON_BIND_SEQFIRST_TO_TUPLE_A __VA_ARGS__) }; \
return keys; \
} \
void to_json(json& j) const \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQMAP_TO_JSON_A __VA_ARGS__) \
} \
bool from_json(const json& j, std::string* err = NULL) \
{ \
if (!j.is_object()) \
{ \
if (err) { *err = std::string("type must be object[") + typeid(*this).name() + "], but is " + std::string(j.type_name()); } \
return false; \
} \
try \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQMAP_FROM_JSON_A __VA_ARGS__) \
return true; \
} \
catch (const std::exception& ex) \
{ \
if (err){ *err = ex.what();} \
} \
return false; \
} \
void _from_json(const json& j) \
{ \
JSON_BIND_SEQ_FOR(JSON_BIND_SEQMAP_FROM_JSON_A __VA_ARGS__) \
} \
JSON_BIND_FUNCTION();
#endif