引用www.json.org上的对JSON这种数据格式的介绍:
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。
简单地说,JSON就是一种基于Javascript的轻量级数据交换格式。它给我的感觉有点类似于xml,但写法更随意,并且用途不同。
这篇文章不会介绍JSON本身,因此,如果您首次接触JSON,请务必先到http://www.json.org/去看完introduction.(这里还有中文版:http://www.json.org/json-zh.html)。
其实操作JSON数据比较方便的还是C#和Java,语句编写也比较简单、方便。C++操作JSON数据相对就要复杂一些,但只要理解了JSON这种数据格式,除了代码字符量大一些以外,操作起来也不是很复杂。
在JSON官网上已经推荐了一些使用C++操作JSON的open source项目,我试用了几种,最后选择了TinyJSON。因为它只需要一个.hpp文件,看起来比较轻量级。但无论是哪种,多数C++操作JSON的项目,都需要使用boost,所以,在正式使用TinyJSON之前,你还需要把boost编译并配置好。我使用的是boost 1.39.0。关于boost的编译和配置,网上已经有很多介绍的文章了,这里就不再说。
说了一些废话,下面言归正传,来看一下如何使用TinyJSON。
先从简单的来,比如我们有这样一段JSON数据:
{ "login_time": 1246068720 }
一目了然,名称是login_time,值是1246068720。用TinyJSON读取,代码就可以这么写:
1string strJson = "{ \"login_time\": 1246068720 }";
2grammar<char>::variant var = parse(strJson.begin(), strJson.end());
3if(var->type() == typeid(grammar<char>::object))
4{
5 grammar<char>::object const& obj = boost::any_cast<grammar<char>::object>(*var);
6 for(grammar<char>::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
7 {
8 std::string strName = (*it).first;//这里你可以读到名称“login_time”
9
10 if((*it).second->type() == typeid(int))
11 {
12 int nValue = boost::any_cast<int>(*(*it).second);//这里将login_time的值读到一个整型变量里。
13 }
14 }
15}
(注,需要事前定义命名空间:using namespace json;,否则你需要写成这样:json::grammer<char>什么什么)JSON数据基本上都是“名称-值”这样的格式,其中“值”有很多类型,比如上面的例子是一个整型,还有字符类型、double、布尔等等。并且“值”不限于这些,还可以是一个数组,甚至又是一段JSON数据。
下面举个“值”是数组的例子,比如这样的一段JSON数据:
{ "auto_harvest": [26,28,25] }相应的读取代码如下:
1string strJson = "{ \"auto_harvest\": [26,28,25] }";
2grammar<char>::variant var = parse(strJson.begin(), strJson.end());
3if(var->type() == typeid(grammar<char>::object))
4{
5 grammar<char>::object const& obj = boost::any_cast<grammar<char>::object>(*var);
6 for(grammar<char>::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
7 {
8 std::string strName = (*it).first; //这里读到名称“auto_harvest”
9
10 if((*it).second->type() == typeid(grammar<char>::array))
11 {
12 //这是一个数组类型,下面循环解析里面所有的元素
13 grammar<char>::array const & a = boost::any_cast<grammar<char>::array>(*(*it).second);
14 for(grammar<char>::array::const_iterator ita = a.begin(); ita != a.end(); ++ita)
15 {
16 if((*ita)->type() == typeid(int))
17 {
18 nValue = boost::any_cast<int>(*(*ita)); //这里会读到每一个数组元素
19 }
20 }
21 }
22 }
23}
再来一段“值”是另外一段JSON的例子,比如你拿到的JSON数据是这样的:
{ "server_now": 1246117129.8, "return_code": 0, "params": {"rekoo_killer": "123456"} }
我们可以将上面的JSON数据分为“两级”,如下:
server_now : 1246117129.8 (第一级)
return_code : 0 (第一级)
param : (第一级)
rekoo_killer : 123456 (第二级)
其中
rekoo_killer : 123456是param的“值”,而
rekoo_killer : 123456本身又可以单独看做一段独立的JSON数据,它在TinyJSON中被作为一个object类型。
用TinyJSON解析上面的JSON数据,代码可以这样写:
1string strJson = "{ \"server_now\": 1246117129.8, \"return_code\": 0, \"params\": {\"rekoo_killer\": \"123456\"} }";
2grammar<char>::variant var = parse(strJson.begin(), strJson.end());
3if(var->type() == typeid(grammar<char>::object))
4{
5 grammar<char>::object const& obj = boost::any_cast<grammar<char>::object>(*var);
6 for(grammar<char>::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
7 {
8 std::string strName = (*it).first;
9
10 if((*it).second->type() == typeid(int))
11 {
12 int nValue = boost::any_cast<int>(*(*it).second); //读到return_code的值0
13 }
14 else if((*it).second->type() == typeid(double))
15 {
16 double dValue = boost::any_cast< double >(*(*it).second); //读到server_now的值1246117129.8
17 }
18 else if((*it).second->type() == typeid(std::string))
19 {
20 std::string strValue = boost::any_cast< std::string >(*(*it).second);
21 }
22 else if((*it).second->type() == typeid(bool))
23 {
24 bool bValue = boost::any_cast< bool >(*(*it).second);
25 }
26 else if((*it).second->type() == typeid(grammar<char>::object))
27 {
28 //params的值会进入这个判断语句来
29
30 grammar<char>::object const & o = boost::any_cast<grammar<char>::object>(*(*it).second);
31 for(grammar<char>::object::const_iterator oo = o.begin(); oo != o.end(); ++oo)
32 {
33 std::string strName = (*oo).first; //这里读到了名称rekoo_killer
34
35 //下面怎么做我就不写了,rekoo_killer的值就是一个整型
36 }
37 }
38 else if((*it).second->empty())
39 {
40 AfxMessageBox(_T("it's a null value"));
41 }
42 else
43 {
44 AfxMessageBox(_T("unknown type!"));
45 }
46 }
47}
相信经过上面的介绍,各位已经对如何使用TinyJSON来读取一段JSON数据有所了解了。