boost variant 介绍
boost variant 是一个不同union的泛型类,它用于存储和操作不同类型但在使用时存在<相同泛型>的对象。variant 在实现不同类型的泛型的同时,提供对其包含的具体类型的安全访问。
基于此性质,boost variant 可以应用于创建json 这种数据结构,我们把json 中的Object, Array, String, Number, True, False, Null 统一当做同一种variant 类型。需要注意的是,json 中的Object 和 Array 类型是递归的variant 类型,在声明时需要使用 boost::recursive_wrapper 修饰。boost::recursivee_wrapper用于创建包含创建的variant类型的表达式。
在访问varint 类型时,可以使用boost::get
更多关于 boost variant 的介绍见:
https://www.boost.org/doc/libs/1_62_0/doc/html/variant/reference.html
json 数据结构
json 的数据类型实现如下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/*************************************************************************
> File Name: json_type.hpp
> Author: ce39906
> Mail: ce39906@163.com
> Created Time: 2018-07-31 16:25:59
************************************************************************/
namespace json
{
struct Object;
struct Array;
struct String
{
String() {}
String(const char* value) : value{value} {}
String(std::string value) : value{std::move(value)} {}
std::string value;
};
struct Number
{
Number() {};
Number(const double value) : value{value} {}
double value;
};
struct True
{
};
struct False
{
};
struct Null
{
};
using Value = boost::variant<String,
Number,
boost::recursive_wrapper<Object>,
boost::recursive_wrapper<Array>,
True,
False,
Null>;
struct Object
{
bool isMember(const std::string& key) const
{
return values.count(key) != 0;
}
const Value& at(const std::string& key) const
{
return values.at(key);
}
const Value& operator[](const std::string& key) const
{
return values.at(key);
}
std::unordered_map<std::string, Value> values;
};
struct Array
{
const Value& at(const size_t idx) const
{
return values.at(idx);
}
const Value& operator[](const size_t idx) const
{
return values.at(idx);
}
size_t size() const
{
return values.size();
}
const Value& front() const
{
return values.front();
}
const Value& back() const
{
return values.back();
}
std::vector<Value> values;
};
} // ns json
json 数据访问
本节只介绍使用boost::get
代码示例如下
1 | namespace access |
json 序列化
json 序列化利用boost::apply_visitor. boost::apply_visitor需要实现一个visitor 函数对象,函数对象针对不同实际类型实现不同的序列化方式,针对Object以及Array 这两种类型需要递归调用visitor。
示例代码如下
1 | /************************************************************************* |
构造json 结构
针对String,Number,True,False,Null 这类简单类型可以直接使用构造函数构造。
Array 类型内部使用vector 类型,构造时使用vector 的 push_back, emplace_back 方法增加Array的元素。
Object 类型内部使用unordered_map 类型,构造时可以使用 unordered_map 的内建方法。
示例代码如下:
1 | Object obj; |
示例
示例代码测试构建json对象,访问json对象,以及序列化json 对象。
示例代码如下
1 | /************************************************************************* |
编译
g++ –std=c++11 test_json.cpp -o test_json
执行
执行结果如下
TODO
使用boost spirit 实现json反序列化
完整代码
https://github.com/ce39906/self-practices/tree/master/cppcode/variant_json