文章目录
  1. 1. 想法
    1. 1.1. 根据json的key直接获取value
    2. 1.2. 获取一个json下所有的key-value
    3. 1.3. 获取json的数组
  2. 2. 插入数据的操作
    1. 2.1. 插入一个key-value
    2. 2.2. 插入一个map
    3. 2.3. 插入一个数组
    4. 2.4. 保存结果
  3. 3. 我的测试详情请访问test_json.cpp
  4. 4. 贴上完整的源代码:
  5. 5. parse_json.h
  6. 6. parse_json.cpp

请注意,这段代码只能运行在boost的版本比较高的情况下。我的ubuntu 14.04LTSboost版本是1.54,所以能编译通过,但是今天我在我的centos 6.5上编译通不过,因为我的centos 6.5boost版本是1.41。我在centos 6.5下是用yum安装boost的命令是

1
2
yum -y groupinstall "Development Tools"
yum -y install boost-*

然而这个yum -y install boost-*在我的zsh环境下执行不了,我只好切换到bash执行。boost安装路劲是/usr/include/boost,然后有一个专门的version.hpp是显示boost版本的,这个时候我查看到我用yum安装的boost1.41版本。随后我重新下载了boost的源代码,使用b2安装了最新版。不得不说centos的软件更新速度真是慢。同样是安装,我的Ubuntu 14.04LTS用的是

1
sudo apt-get install libboost-all-dev

安装的boost就是1.54版本。

=========================== 2015年12月13日 ========================================

解析json由于没有attribute,相比解析xml少了很多繁文缛节。把这篇博客和我上一篇博客《使用boost::property_tree解析xml与json (二):parse_xml设计》对比起来看理解起来会很容易。

想法

解析json,我觉得有以下几种情况:

根据jsonkey直接获取value

接口是这样子的:

1
string GetChildData(const string& path);

比如说这样的一个json

1
2
3
4
5
6
7
8
9
10
{ 
"root":
{
"child":
{
"a": "1",
"b": "2"
}
}
}

使用:

1
pt.GetChildData("root.child.a")

就能获取到a的值。

获取一个json下所有的key-value

在上面的例子当中,就是获取root.child下面的ab

接口为:

1
map<string, string> GetChildDataMap(const string& path);

由于json的格式都是key-value型,使用map简直是最适合不过了。唯一需要注意的就是同一个元素当中不能有相同的key,否则写到map 当中会覆盖掉原来的值,这种情况我觉的大可不必担心,因为在写json配置文件的时候自然会考虑到不能写重复的key值,所以我在这里用的是map而不是mutilmap

1
pt.GetChildData("root.child") 

获取json的数组

接口格式是这样:

1
vector<map<string, string> > GetChildDataArray(const string& path);

如果想要获取child这个数组的话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ 
"root":
{
"child":
[
{
"a": "1",
"b": "2"
},
{
"a": "1",
"b": "2"
}
]
}
}

使用方法为

1
pt.GetChildDataArray("root.child")

刚刚好child这个数组的每一个元素都没有名字,vector也不保存名字。而数组的每个元素当中的key-value刚刚好就是一个pair

插入数据的操作

插入一个key-value

使用

1
void PutChildData(const string& key, const string& value);

比如要在

1
2
3
4
5
6
7
8
9
10
{ 
"root":
{
"child":
{
"a": "1",
"b": "2"
}
}
}

当中插入一行key-value,就可以用这个接口

1
pt.PutChildData("testput", "testput")

最后得到:

1
2
3
4
5
6
7
8
9
10
11
{ 
"root":
{
"child":
{
"a": "1",
"b": "2"
}
},
"testput": "testput"
}

这个接口当中封装的property_tree方法会自动添加逗号。

插入一个map

与上面的

1
map<string, string> GetChildDataMap(const string& path);

相对应的就是这个接口:

1
void PutChildDataMap(const string& key, const map<string, string>& key_value_map);

比如要在当中加入一个和child相同的map

1
2
3
4
5
6
7
8
9
10
{ 
"root":
{
"child":
{
"a": "1",
"b": "2"
}
}
}

使用方法:

1
2
3
myMap.insert(make_pair("a", "1"));
myMap.insert(make_pair("b", "2"));
PutChildData("root.newchild", myMap);

运行结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{ 
"root":
{
"child":
{
"a": "1",
"b": "2"
},
"newchild":
{
"a": "1",
"b": "2"
}
}
}

插入一个数组

同样的和上面的get接口相对应的put接口:

1
void PutChildDataArray(const string& key, const vector<map<string, string> >& array_list);

比如对这个json进行操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ 
"root":
{
"child":
[
{
"a": "1",
"b": "2"
},
{
"a": "1",
"b": "2"
}
]
}
}

使用方法:

1
2
3
4
5
6
7
8
myMap.insert(make_pair("a", "1"));
myMap.insert(make_pair("b", "2"));
yourMap.insert(make_pair("a", "1"));
yourMap.insert(make_pair("b", "2"));
vector<map<string, string> > array;
array.push_back(myMap);
array.push_back(yourMap);
PutChildData("root.nee", array);

运行结果为:

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
{ 
"root":
{
"child":
[
{
"a": "1",
"b": "2"
},
{
"a": "1",
"b": "2"
}
],
"nee":
[
{
"a": "1",
"b": "2"
},
{
"a": "1",
"b": "2"
}
]
}
}

保存结果

在对json进行写入之后,不要忘记调用接口

1
void SaveConfig();

来保存结果。
这个和xml的操作是一样的。

我的测试详情请访问test_json.cpp

贴上完整的源代码:

parse_json.h

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
#ifndef MQUEUE_INCLUDE_PARSE_JSON_H_
#define MQUEUE_INCLUDE_PARSE_JSON_H_

/* 以前一直都是把解析json文件的代码放在池的构造函数当中,这里把它独立出来
* 使用boost的json解析库,也推荐使用rapidjson,
* rapidjson是仿造rapidxml写出来的,不过没有用在boost库当中
*/

#include <string>
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/property_tree/ptree.hpp>

using std::string;
using std::vector;
using std::map;
using std::make_pair;
using boost::property_tree::ptree;

typedef boost::shared_ptr<boost::property_tree::ptree> ptreePtr;

class ParseJsonObj {
public:
explicit ParseJsonObj();
explicit ParseJsonObj(string configPath);
virtual ~ParseJsonObj();
ParseJsonObj(const ParseJsonObj&) = delete;
ParseJsonObj& operator=(const ParseJsonObj&) = delete;
void Dump() const;

string GetConfigPath() const;

ptreePtr GetPtree() const;

/*
* GetChildData("root.child.a") will get "a"
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* }
* }
* }
*/
string GetChildData(const string& path);

/*
* GetChildData("root.child") will get "a" and "b"
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* }
* }
* }
*/
map<string, string> GetChildDataMap(const string& path);

/*
* GetChildDataArray("root.child") will get "a" and "b"
* { "root":
* { "child":
* [
* { "a": "1",
* "b": "2"
* },
* { "a": "1",
* "b": "2"
* }
* ]
* }
* }
*/
vector<map<string, string> > GetChildDataArray(const string& path);

//===========================================================
/*
* PutChildData("testput", "testput") will add "testput" in
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* }
* }
* }
* new:
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* }
* },
* "testput": "testput"
* }
*/
void PutChildData(const string& key, const string& value);

/*
* myMap.insert(make_pair("a", "1")) myMap.insert(make_pair("b", "2"))
* PutChildData("root.newchild", myMap) will add "newchild" in
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* }
* }
* }
* new:
* { "root":
* { "child":
* { "a": "1",
* "b": "2"
* },
* "newchild":
* { "a": "1",
* "b": "2"
* }
* }
* }
*/
void PutChildDataMap(const string& key, const map<string, string>& key_value_map);

/*
* myMap.insert(make_pair("a", "1")) myMap.insert(make_pair("b", "2"))
* yourMap.insert(make_pair("a", "1")) yourMap.insert(make_pair("b", "2"))
* vector<map<string, string> > array; array.push_back(myMap); array.push_back(yourMap);
* PutChildData("root.nee", array) will add "nee" in
* { "root":
* { "child":
* [
* { "a": "1",
* "b": "2"
* },
* { "a": "1",
* "b": "2"
* }
* ]
* }
* }
* new:
* { "root":
* { "child":
* [
* { "a": "1",
* "b": "2"
* },
* { "a": "1",
* "b": "2"
* }
* ],
* "nee":
* [
* { "a": "1",
* "b": "2"
* },
* { "a": "1",
* "b": "2"
* }
* ]
* }
* }
*/
void PutChildDataArray(const string& key, const vector<map<string, string> >& array_list);

/*
* save config
*/
void SaveConfig();

private:
string configPath_;
//这里不用ptree对象而用指针的意义在于如果使用ptree对象的话,构造的时候就必须完全构造这个对象
ptreePtr pt_;
//ptree* pt_;
};

typedef boost::shared_ptr<ParseJsonObj> ParseJsonObjPtr;
#endif /* MQUEUE_INCLUDE_PARSE_JSON_H */

parse_json.cpp

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
#include "MQueue/parse_json.h"
#include <boost/property_tree/json_parser.hpp>


ParseJsonObj::ParseJsonObj()
: pt_(new ptree) {
configPath_ = "../config/messageQueue.json";
//pt_ = new ptree;
boost::property_tree::read_json(configPath_, *pt_);
}

ParseJsonObj::ParseJsonObj(string configPath)
: configPath_(configPath), pt_(new ptree) {
//pt_ = new ptree;
boost::property_tree::read_json(configPath_, *pt_);
}

ParseJsonObj::~ParseJsonObj() {
//delete pt_;
}

void ParseJsonObj::Dump() const {
printf("\n=====ParseJsonObj Dump START ========== \n");
printf("configPath__=%s ", configPath_.c_str());
//printf("pt_=%p ", pt_);
printf("\n===ParseJsonObj DUMP END ============\n");
}

string ParseJsonObj::GetConfigPath() const {
return configPath_;
}

ptreePtr ParseJsonObj::GetPtree() const {
return pt_;
}

string ParseJsonObj::GetChildData(const string& path) {
return pt_->get<string>(path);
}

map<string, string> ParseJsonObj::GetChildDataMap(const string& path) {
map<string, string> key_value_map;

auto child = pt_->get_child(path);
for (auto pos = child.begin(); pos!= child.end(); ++pos) {
key_value_map.insert(make_pair(pos->first, pos->second.data()));
}
return std::move(key_value_map);
}

vector<map<string, string> > ParseJsonObj::GetChildDataArray(const string& path) {
vector<map<string, string> > result_array;
map<string, string> key_value_map;

auto child = pt_->get_child(path);
for (ptree::value_type &v : child.get_child("")) {
auto nextchild = v.second.get_child("");
for (auto pos = nextchild.begin(); pos!= nextchild.end(); ++pos) {
key_value_map.insert(make_pair(pos->first, pos->second.data()));
}
result_array.push_back(key_value_map);
key_value_map.clear();
}
return std::move(result_array);
}

void ParseJsonObj::PutChildData(const string& key, const string& value) {
if(pt_ != NULL) {
pt_->put(key, value);
}
}

void ParseJsonObj::PutChildDataMap(const string& key, const map<string, string>& key_value_map) {
if(pt_ != NULL) {
ptree child;
for (auto myPair : key_value_map) {
child.put(myPair.first, myPair.second);
}
pt_->add_child(key, child);
}
}

void ParseJsonObj::PutChildDataArray(const string& key, const vector<map<string, string> >& array_list) {
if(pt_ != NULL) {
ptree first;
for (auto key_value_map : array_list) {
ptree second;
for (auto myPair : key_value_map) {
second.put(myPair.first, myPair.second);
}
first.push_back(make_pair("", second));
}
pt_->add_child(key, first);
}
}

void ParseJsonObj::SaveConfig() {
if(pt_ != NULL) {
boost::property_tree::write_json(configPath_, *pt_);
}
}

文章目录
  1. 1. 想法
    1. 1.1. 根据json的key直接获取value
    2. 1.2. 获取一个json下所有的key-value
    3. 1.3. 获取json的数组
  2. 2. 插入数据的操作
    1. 2.1. 插入一个key-value
    2. 2.2. 插入一个map
    3. 2.3. 插入一个数组
    4. 2.4. 保存结果
  3. 3. 我的测试详情请访问test_json.cpp
  4. 4. 贴上完整的源代码:
  5. 5. parse_json.h
  6. 6. parse_json.cpp