我的玻璃盒子

【原创】TinyJSON使用介绍

引用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数据有所了解了。

posted on 2009-08-05 11:56 深蓝色系统 阅读(5623) 评论(6)  编辑 收藏 引用 所属分类: 皮皮片片

评论

# re: 【原创】TinyJSON使用介绍 2009-08-05 15:59 不戒大师

终于等到了,看了之后 终于不迷糊了,感觉始终是没有C#的方便啊。
我稍加封装了一下,免强好用一点了
http://www.5xp.net/Article/9.aspx  回复  更多评论   

# re: 【原创】TinyJSON使用介绍 2009-08-05 20:10 chentan

chrome 里面提供的json非常好用, 不依赖boost  回复  更多评论   

# re: 【原创】TinyJSON使用介绍 2009-08-06 09:05 远古毛利人

不错,不知道是不是基于Spirit的,楼主是否介意我把它转摘到cppprog.com里?我的这个网站专门收集各种C++库的应用文章。谢谢!  回复  更多评论   

# re: 【原创】TinyJSON使用介绍 2009-08-11 23:14 深蓝色系统

@远古毛利人
可以转载。不过你的网站似乎有些问题,我在家里可以访问,在公司就不行。不知道怎么回事。你的网站不错,挺好的,我也看到了一些我感兴趣的技术文章。  回复  更多评论   

# re: 【原创】TinyJSON使用介绍 2009-08-16 13:14 远古毛利人

非常感谢,因为最近服务器因“原始人”托管商跑路换了而换了IP,DNS服务器也改了一下,所以有点地方可能要等ISP更新DNS缓存才行。  回复  更多评论   

# re: 【原创】TinyJSON使用介绍 2009-09-07 14:15 true

浅显易懂  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


导航

<2009年8月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

常用链接

留言簿(75)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜