原文链接
引用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读取,代码就可以这么写:
string strJson = "{ \"login_time\": 1246068720 }";
grammar::variant var = parse(strJson.begin(), strJson.end());
if(var->type() == typeid(grammar::object))
{
grammar::object const& obj = boost::any_cast::object>(*var);
for(grammar::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
{
std::string strName = (*it).first;//这里你可以读到名称“login_time”
if((*it).second->type() == typeid(int))
{
int nValue = boost::any_cast(*(*it).second);//这里将login_time的值读到一个整型变量里。
}
}
}
(注,需要事前定义命名空间:using namespace json;,否则你需要写成这样:json::grammer
JSON数据基本上都是“名称-值”这样的格式,其中“值”有很多类型,比如上面的例子是一个整型,还有字符类型、double、布尔等等。并且“值”不限于这些,还可以是一个数组,甚至又是一段JSON数据。
下面举个“值”是数组的例子,比如这样的一段JSON数据:
{ "auto_harvest": [26,28,25] }
相应的读取代码如下:
string strJson = "{ \"auto_harvest\": [26,28,25] }";
grammar::variant var = parse(strJson.begin(), strJson.end());
if(var->type() == typeid(grammar::object))
{
grammar::object const& obj = boost::any_cast::object>(*var);
for(grammar::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
{
std::string strName = (*it).first; //这里读到名称“auto_harvest”
if((*it).second->type() == typeid(grammar::array))
{
//这是一个数组类型,下面循环解析里面所有的元素
grammar::array const & a = boost::any_cast::array>(*(*it).second);
for(grammar::array::const_iterator ita = a.begin(); ita != a.end(); ++ita)
{
if((*ita)->type() == typeid(int))
{
nValue = boost::any_cast(*(*ita)); //这里会读到每一个数组元素
}
}
}
}
}
再来一段“值”是另外一段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数据,代码可以这样写:
string strJson = "{ \"server_now\": 1246117129.8, \"return_code\": 0, \"params\": {\"rekoo_killer\": \"123456\"} }";
grammar::variant var = parse(strJson.begin(), strJson.end());
if(var->type() == typeid(grammar::object))
{
grammar::object const& obj = boost::any_cast::object>(*var);
for(grammar::object::const_iterator it = obj.begin(); it != obj.end(); ++it)
{
std::string strName = (*it).first;
if((*it).second->type() == typeid(int))
{
int nValue = boost::any_cast(*(*it).second); //读到return_code的值0
}
else if((*it).second->type() == typeid(double))
{
double dValue = boost::any_cast< double >(*(*it).second); //读到server_now的值1246117129.8
}
else if((*it).second->type() == typeid(std::string))
{
std::string strValue = boost::any_cast< std::string >(*(*it).second);
}
else if((*it).second->type() == typeid(bool))
{
bool bValue = boost::any_cast< bool >(*(*it).second);
}
else if((*it).second->type() == typeid(grammar::object))
{
//params的值会进入这个判断语句来
grammar::object const & o = boost::any_cast::object>(*(*it).second);
for(grammar::object::const_iterator oo = o.begin(); oo != o.end(); ++oo)
{
std::string strName = (*oo).first; //这里读到了名称rekoo_killer
//下面怎么做我就不写了,rekoo_killer的值就是一个整型
}
}
else if((*it).second->empty())
{
AfxMessageBox(_T("it's a null value"));
}
else
{
AfxMessageBox(_T("unknown type!"));
}
}
}
相信经过上面的介绍,各位已经对如何使用TinyJSON来读取一段JSON数据有所了解了。