Cocos2d-x学习(五):cocos2d-x解析json(使用libjson库)

来源:互联网 发布:windows redmine 迁移 编辑:程序博客网 时间:2024/05/02 02:31

cocos2d-x很好,扩展性很好,但是其第三方库还不是很成熟,正如王哲所说,需要我们自己寻找,比如json解析和格式化。


我们的网络部分需要用到json,网络部分用的比较多的就是json,毕竟很轻量级么。。。上午我看到cocos2d-x论坛里关于json的第三方库有人提到了两个,一个是jsoncpp,一个是libjson,我上午首选的是jsoncpp,看其编译过程,是比较复杂的,我耐着性子又下了scons(编译器),编是编出来了,可是在iphone上会报link的错,不知其解,在Mac app中使用,正常。。。擦,原来是Mac是64位的,而iphone需要的是32位库的,又是各种找答案,终于在其官网的wiki上找到解答-------在Mac 64位上编出32位库的方法,试了,发现编不过去,好像是gcc版本的原因,再看下面的warning,上面说对Mac的支持就是不怎么样!好吧,我承认它不是跨iphone和android的最佳选择了。(在ubuntu上编译很轻松,没问题的,应该android上没问题),于是下午我就转向了libjson。


1.json介绍

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

JSON建构有两种结构:

  1. “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),记录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
  2.值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

(ps:这两段是从百度百科上copy的,但是json的第2种结构很重要,是人们常常忽视的)


2.编译

论坛里也有人提问过libjson怎么用,王哲给出的答案是直接copy源码到工程里,想必没有太复杂的编译参数,环境之类的障碍,于是我就copy了,编译,没错!工程如图

(copy了libjson下的Source,Dependencies目录和JSONOptions.h,libjson.h)


(PS: 只所以把光标放在JSONOptions.h上,是因为它很邪恶,几个宏和其开关的用法,源码竟然还有个bug。。。)


3.用法

libjson为我们提供了两套接口,一套c的,一套c++的,在其目录的Getting Started目录下,至于选择就因人喜好了!


(1)简单写法:

[cpp] view plaincopy
  1. <span style="font-size:16px;">JSONNODE *n = json_new(JSON_NODE);  
  2.     json_push_back(n, json_new_i("number", 88));  
  3.     json_push_back(n, json_new_a("string""oneRain"));  
  4.     json_push_back(n, json_new_a("charactor""中文"));  
  5.       
  6.     json_char *jc = json_write_formatted(n);  
  7.     CCLOG("json: %s", jc);  
  8.     json_free(jc);  
  9.     json_delete(n);</span>  
输出结果:


(2)简单读法:

读取就需要一个简单的解析过程了,当然也可以没有,如果没有键的话

[cpp] view plaincopy
  1. <span style="font-size:16px;">void ParseJSON(JSONNODE *n)  
  2. {  
  3.     if (n == NULL){  
  4.         printf("Invalid JSON Node1\n");  
  5.         return;  
  6.     }  
  7.       
  8.     JSONNODE_ITERATOR i = json_begin(n);  
  9.     while (i != json_end(n)){  
  10.         if (*i == NULL){  
  11.             printf("Invalid JSON Node2\n");  
  12.             return;  
  13.         }  
  14.           
  15.         // recursively call ourselves to dig deeper into the tree  
  16.         if (json_type(*i) == JSON_ARRAY || json_type(*i) == JSON_NODE){  
  17.             ParseJSON(*i);  
  18.         }  
  19.           
  20.         // get the node name and value as a string  
  21.         json_char *node_name = json_name(*i);  
  22.           
  23.         // find out where to store the values  
  24.         if (strcmp(node_name, "number") == 0){  
  25.             json_int_t node_value = json_as_int(*i);  
  26.             CCLOG("%d", node_value);  
  27.         }  
  28.         else if (strcmp(node_name, "string") == 0){  
  29.             json_char *node_value = json_as_string(*i);  
  30.             CCLOG("%s", node_value);  
  31.             json_free(node_value);  
  32.         }  
  33.         else if (strcmp(node_name, "charactor") == 0)  
  34.             CCLOG("%s", json_as_string(*i));  
  35.           
  36.         // cleanup and increment the iterator  
  37.         json_free(node_name);  
  38.         ++i;  
  39.     }  
  40. }</span>  
调用过程

[cpp] view plaincopy
  1. <span style="font-size:16px;">char *json = "{\"number\":88,\"string\":\"oneRain\",\"charactor\":\"汉字\"}";  
  2.     JSONNODE *nr = json_parse(json);  
  3.     ParseJSON(nr);  
  4.     json_delete(nr);</span>  
结果如图:


(3)json数组

很多时候我们需要json格式来存储数组,有可能是对象的数组,也可能是基本变量的数组,如果是对象数组的话,就需要在“简单读法”中的ParseJSON方法中添加一些对对象的申请和对链表的操作才能完成你想要的数据结构!

当然另一种比较常用的用法是:只有“值”,没有“键”的数组,比如 ["value1","value2","value3"],这种格式是常用于socket链接中与服务器通信的,下面就分别写一个解析和格式化的两种方式:

a.解析

当然还是需要一个解析的函数用来输出和递归用的

[cpp] view plaincopy
  1. <span style="font-size:16px;">void parseArrJSON(JSONNODE *n)  
  2. {  
  3.     if (n == NULL)  
  4.     {  
  5.         CCLOG("Invalid JSON Node\n");  
  6.         return;  
  7.     }  
  8.       
  9.     // Parser  
  10.     JSONNODE_ITERATOR it = json_begin(n);  
  11.     while (it != json_end(n)) {  
  12.         if (*it == NULL) {  
  13.             CCLOG("Invalid JSON Node\n");  
  14.             return;  
  15.         }  
  16.           
  17.         if (json_type(*it) == JSON_ARRAY || json_type(*it) == JSON_NODE) {  
  18.             parseArrJSON(*it);  
  19.         }  
  20.         else {  
  21.             // 如果只是值没有键,则只需要获取即可  
  22.             json_char *value = json_as_string(*it);  
  23.             CCLOG("%s", value);  
  24.             json_free(value);  
  25.         }  
  26.           
  27.         ++it;  
  28.     }  
  29.       
  30. }  
  31. </span>  
用法很简单

[cpp] view plaincopy
  1. <span style="font-size:16px;">char *arrJson = "[\"value1\",\"value2\",\"value3\"]";  
  2.     JSONNODE *an = json_parse(arrJson);  
  3.     parseArrJSON(an);  
  4.     json_delete(an);</span>  

b.格式化

也就是拼接json字符串了

[cpp] view plaincopy
  1. <span style="font-size:16px;">JSONNODE *arrn = json_new(JSON_ARRAY);  
  2.     json_set_name(n, NULL);  
  3.     json_push_back(n, json_new_a(NULL, "one"));  
  4.     json_push_back(n, json_new_a(NULL, "汉字"));  
  5.     json_push_back(n, json_new_i(NULL, 999999));  
  6.       
  7.     json_char *arrjc = json_write(arrn);  
  8.       
  9.     CCLOG("Json: %s, %d", arrjc, strlen(jc));</span>  

需要注意的是如果不想要“键”,则将对应参数设置为NULL,对象中不能这样做,数组中可以


特别PS:如果希望汉字原样输出,而不转化成utf-8编码格式,需要将JSONOptions.h中的宏关闭

[cpp] view plaincopy
  1. <span style="font-size:16px;">#define JSON_ESCAPE_WRITES</span>  

代码下载


5-24记录:libjson中判断结点类型c方法json_type(const void *node)

已定义类型

[cpp] view plaincopy
  1. #define JSON_NULL '\0'  
  2. #define JSON_STRING '\1'  
  3. #define JSON_NUMBER '\2'  
  4. #define JSON_BOOL '\3'  
  5. #define JSON_ARRAY '\4'  
  6. #define JSON_NODE '\5'  

原创粉丝点击