1. 程式人生 > >cjson使用筆記(轉)

cjson使用筆記(轉)

                                                                                                        緣      起                                                                                                     

      最近在stm32f103上做一個智慧家居的專案,其中選擇的實時作業系統是 rt_thread OS v1.2.2穩定版本,其中涉及到C和java(android)端資料的交換問題,經過討論和研究,選擇了json格式的資料進行互動。當然,如果自己去寫一個json解析器,有點重造輪子的嫌疑。於是使用了開源的json解析器。考慮到是嵌入式平臺,在一位朋友的推薦下,選擇了輕量級別的cJSON。

                                                                                                        使      用                                                                                                     

       cJSON 開源專案位置:  http://sourceforge.net/projects/cjson/

       cJSON,目前來說,就只有兩個檔案,一個cJSON.c 一個cJSON.h檔案。使用的時候,自己建立好一個main.c檔案後,如果是在linux pc上,請使用以下命令進行編譯:

1 gcc -g -Wall *.c -l m

就會預設生成一個 a.out檔案,執行即可。在linux下編譯的時候,注意連結 libm 庫。

       整個專案都是以極標準的C來寫的,意思說,可以跨各種平臺使用了。不過,還是有兩三處需要微調一下<針對stm32f103  + rt_thread >。其中修改一下malloc & free & size_t 這三個東西:

 46 static void *(*cJSON_malloc)(size_t sz) = malloc;
 47 static void (*cJSON_free)(void *ptr) = free;
---------------------------------------- 46 static void *(*cJSON_malloc)(size_t sz) = rt_malloc; 47 static void (*cJSON_free)(void *ptr) = rt_free;
複製程式碼
 60 void cJSON_InitHooks(cJSON_Hooks* hooks)
 61 {
 62     if (!hooks) { /* Reset hooks */
 63         cJSON_malloc = malloc;
 64         cJSON_free = free;
 65         return;
 66     }
 67 
 68     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
 69     cJSON_free   = (hooks->free_fn)?hooks->free_fn:free;
 70 }
----------------------------------------------------
 60 void cJSON_InitHooks(cJSON_Hooks* hooks)
 61 {
 62     if (!hooks) { /* Reset hooks */
 63         cJSON_malloc = rt_malloc;
 64         cJSON_free = rt_free;
 65         return;
 66     }
 67 
 68     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:rt_malloc;
 69     cJSON_free   = (hooks->free_fn)?hooks->free_fn:rt_free;
 70 }
複製程式碼

free & malloc就這麼兩個地方要修改一下吧,其中size_t 這個應該是在 .h 檔案修改,主要是rtt的 rt_malloc 和這裡的malloc使用的不同,所以修改了下---不一定非要修改。

所以,這東西說實話,也不存在什麼移植不移植的問題了。很輕鬆的就可以在各個平臺使用了。

                                                                                                   例       程                                                                                                          

      不對json的格式進行說明了,下面直接記下使用方法了。

      第一,建立json資料串。這資料串,可能是物件,也可能是陣列,也可能是它們的各種組合,其中再加上一些鍵值對。有一點要先說明:它們的組合,符合父子繼承格式--這也是json資料串的特點。

     <1>  建立一個物件,並在這個物件裡面新增一個字串鍵值和一個數字鍵值:

複製程式碼
 1 int create_js(void)
 2 {
 3     cJSON *root;
 4     /*create json string root*/
 5     root = cJSON_CreateObject();
 6     if(!root) {
 7         DEBUG("get root faild !\n");
 8         goto EXIT;
 9     }else DEBUG("get root success!\n");
10 
11     {
12         cJSON * js_body ;
13 
14         const char *const body = "body";
15         cJSON_AddItemToObject(root, body, js_body=cJSON_CreateObject());
16         cJSON_AddStringToObject(js_body,"name","xiaohui");
17         cJSON_AddNumberToObject(js_body,"value",600);
18         {
19         char *s = cJSON_PrintUnformatted(root);
20         if(s){
21             DEBUG("create js string is %s\n",s);
22             free(s);
23         }
24         }
25         cJSON_Delete(root);
26     }
27 
28     return 0;
29 EXIT:
30     return -1;
31 }
32 
33 int main(int argc, char **argv)
34 {
35     create_js();
36     return 0;
37 }
複製程式碼

執行結果:

1 create js string is  {"body":{"name":"xiaohui","value":600}}

說明: 建立根物件,使用  cJSON_CreateObject(); 這個API,返回的是一個 cJSON的指標,注意,在這個指標用完了以後,需要手工呼叫 cJSON_Delete(root); 進行記憶體回收。

建立body物件的時候,是在根物件的基礎上進行建立,而插入name 和value的時候,是以body為父節點。需要注意的是  json 格式的資料,雖然也是一個字串的樣子,但這個時候還是無法當成普通的字串進行使用,需要呼叫 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);來將json物件轉換成普通的字串,並且都是以該json物件的根為基點。兩個API的區別即是:一個是沒有格式的:也就是轉換出的字串中間不會有"\n" "\t"之類的東西存在,而cJSON_Print(root);打印出來是人看起來很舒服的格式。僅此而已。

<2> 建立一個數組,並向陣列新增一個字串和一個數字:

複製程式碼
 1 int create_js(void)
 2 {
 3     cJSON *root, *js_body;
 4     root = cJSON_CreateArray();
 5     cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
 6     cJSON_AddItemToArray(root, cJSON_CreateNumber(10)); 
 7     {
 8 //        char *s = cJSON_Print(root);
 9         char *s = cJSON_PrintUnformatted(root);
10         if(s){
11             DEBUG(" %s \n",s);
12             free(s);
13         }
14     }
15     if(root)
16     cJSON_Delete(root);
17 
18     return 0;
19 EXIT:
20     return -1;
21 }
22 
23 int main(int argc, char **argv)
24 {
25     create_js();
26     return 0;
27 }
複製程式碼

執行結果:

1 ["Hello world",10]

<3> 物件裡面包括一個數組,數組裡麵包括物件,物件裡面再新增一個字串和一個數字:

複製程式碼
 1 int create_js(void)
 2 {
 3     cJSON *root, *js_body, *js_list;
 4     root = cJSON_CreateObject();
 5     cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray());
 6     cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject());
 7     cJSON_AddStringToObject(js_list,"name","xiaohui");
 8     cJSON_AddNumberToObject(js_list,"status",100);
 9 
10     {
11         //        char *s = cJSON_Print(root);
12         char *s = cJSON_PrintUnformatted(root);
13         if(s){
14             DEBUG(" %s \n",s);
15             free(s);
16         }
17     }
18     if(root)
19         cJSON_Delete(root);
20 
21     return 0;
22 EXIT:
23     return -1;
24 }
25 
26 int main(int argc, char **argv)
27 {
28     create_js();
29     return 0;
30 }
複製程式碼

執行結果:

1 {"body":[{"name":"xiaohui","status":100}]}

<4>其他組合就依次類推,只要搞清楚父子關係即可。隨便巢狀隨便玩。不再貼了。

   <第二, 解析json資料串>

   步驟: 1  先將普通的json 字串 處理成 json物件格式。 2  根據關鍵字進行解析,解析的時候,需要根據關鍵字值的型別進行判斷,而這些型別,已經在cJSON.h裡面寫明白了,包括:物件、陣列、普通字串、普通變數等等。

   <偷個懶吧,將自己學習的時候用的資料現貼過來,後面休息一下再詳細補充自己在工程中的解析方法>

http://blog.csdn.net/xukai871105/article/details/17094113

http://blog.sina.com.cn/s/blog_a6fb6cc90101ffme.html

<當然,他寫的比較簡潔,還有些可以補充的---其實我已經在上面使用文字進行補充過了。當然,不同的工程,可能解析的方法和側重點並不相同>

或許,是時候把解析的部分補充上來了:

處理流程:

1, 先將普通的json串處理成json物件,也就是所謂的建立json root的過程,只有一行程式碼即可:

cJSON *root;
root = cJSON_Parse(js_string);

ps:需要注意的是,這個root在解析完成後,需要釋放掉,程式碼如下:

if (root)
  cJSON_Delete(root);

2,開始拿關鍵字,但如果關鍵字還有父層或者祖層,那就需要先從父層開拿,所謂剝洋蔥是也!

先說沒有父層的:

{"name":"xiaohong","age":10}

這個字串這樣拿即可:

複製程式碼
 1 char *s = "{\"name\":\"xiao hong\",\"age\":10}";
 2 cJSON *root = cJSON_Parse(s);
 3 if(!root) {
 4     printf("get root faild !\n");
 5     return -1;
 6 }
 7 cJSON *name = cJSON_GetObjectItem(root, "name");
 8 if(!name) {
 9     printf("No name !\n");
10     return -1;
11 }
12 printf("name type is %d\n",name->type);
13 printf("name is %s\n",name->valuestring);
14 
15 cJSON *age = cJSON_GetObjectItem(root, "age");
16 if(!age) {
17     printf("no age!\n");
18     return -1;
19 }
20 printf("age type is %d\n", age->type);
21 printf("age is %d\n",age->valueint);
複製程式碼

顯示結果:

1 name type is 4
2 name is xiao hong
3 age type is 3
4 age is 10

需要注意的是: 上面的type 已經在cJSON.h裡面定義好了,有自己的意義。如果是在嚴格的場所,應該先判定該 item的type,然後再考慮去拿值。

而如果有父層的話,無非就是接著向下拿就是了,稍微修改下前面的demo吧:

處理這串資料吧:

{\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}
複製程式碼
 1 char *s = "{\"list\":{\"name\":\"xiao hong\",\"age\":10},\"other\":{\"name\":\"hua hua\"}}";
 2 cJSON *root = cJSON_Parse(s);
 3 if(!root) {
 4     printf("get root faild !\n");
 5     return -1;
 6 }
 7 
 8 cJSON *js_list = cJSON_GetObjectItem(root, "list");
 9 if(!js_list) {
10     printf("no list!\n");
11     return -1;
12 }
13 printf("list type is %d\n",js_list->type);
14 
15 cJSON *name = cJSON_GetObjectItem(js_list, "name");
16 if(!name) {
17     printf("No name !\n");
18     return -1;
19 }
20 printf("name type is %d\n",name->type);
21 printf("name is %s\n",name->valuestring);
22 
23 cJSON *age = cJSON_GetObjectItem(js_list, "age");
24 if(!age) {
25     printf("no age!\n");
26     return -1;
27 }
28 printf("age type is %d\n", age->type);
29 printf("age is %d\n",age->valueint);
30 
31 cJSON *js_other = cJSON_GetObjectItem(root, "other");
32 if(!js_other) {
33     printf("no list!\n");
34     return -1;
35 }
36 printf("list type is %d\n",js_other->type);
37 
38 cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
39 if(!js_name) {
40     printf("No name !\n");
41     return -1;
42 }
43 printf("name type is %d\n",js_name->type);
44 printf("name is %s\n",js_name->valuestring);
45 
46 if(root)
47     cJSON_Delete(root);
48     return 0;
複製程式碼

列印結果:

複製程式碼
1 list type is 6
2 name type is 4
3 name is xiao hong
4 age type is 3
5 age is 10
6 list type is 6
7 name type is 4
8 name is hua hua
複製程式碼

所謂子子孫孫無窮盡也,按照上面那個方法推下去即可。

3,json 裡陣列怎麼取?

1 {\"list\":[\"name1\",\"name2\"]}

程式碼如下:

複製程式碼
 1 int main(int argc, char **argv)
 2 {
 3 char *s = "{\"list\":[\"name1\",\"name2\"]}";
 4 cJSON *root = cJSON_Parse(s);
 5 if(!root) {
 6     printf("get root faild !\n");
 7     return -1;
 8 }
 9 cJSON *js_list = cJSON_GetObjectItem(root, "list");
10 if(!js_list){
11     printf("no list!\n");
12     return -1;
13 }
14 int array_size = cJSON_GetArraySize(js_list);
15 printf("array size is %d\n",array_size);
16 int i = 0;
17 cJSON *item;
18 for(i=0; i< array_size; i++) {
19     item = cJSON_GetArrayItem(js_list, i);
20     printf("item type is %d\n",item->type);
21     printf("%s\n",item->valuestring);
22 }
23 
24 if(root)
25     cJSON_Delete(root);
26     return 0;
27 }
複製程式碼

對頭,好簡單的樣子<在別人的庫上使用>

4  如果json數組裡面又搞了物件怎麼辦? 

相關推薦

cjson使用筆記

                                                                                                        緣      起                                          

Python Click 學習筆記

col 輸出 小工具 方法 chm 好的 put name 回調 原文鏈接:Python Click 學習筆記 Click 是 Flask 的團隊 pallets 開發的優秀開源項目,它為命令行工具的開發封裝了大量方法,使開發者只需要專註於功能實現。恰好我最近在開發的一個小

ES6重點--筆記

ava 例如 ring func arrow tps 新建 方程 document 最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, d

MySQL性能優化的筆記

ora 在一起 PC 當我 spa delet CP xpl 打開 今天,數據庫的操作越來越成為整個應用的性能瓶頸了,這點對於Web應用尤其明顯。關於數據庫的性能,這並不只是DBA才需要擔心的事,而這更是我們程序員需要去關註的事情。當我們去設計數據庫表結構,對操作數據庫時(

終極演算法:機器學習和人工智慧如何重塑世界筆記

終極演算法:機器學習和人工智慧如何重塑世界筆記 2017年08月17日 11:00:38 Notzuonotdied 閱讀數:4492 版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Notzuonotdied/artic

《圖解HTTP》讀書筆記

reference:https://www.cnblogs.com/edisonchou/p/6013450.html         目前國內講解HTTP協議的書是在太少了,記憶中有兩本被譽為經典的書《HTTP權威指南》與《TCP/IP詳解,卷1》

字尾陣列學習筆記

字尾陣列學習筆記 轉載來源:https://www.cnblogs.com/Mychael/p/8282898.html 字尾陣列,顧名思義,一定與字尾有關。字尾陣列簡稱sa,sa[i]表示在字串s的所有後綴中,排名第i的字尾的首字母在字串中的位置。【排名從0開始】 比如,對於字串"abab

C++之STL總結精華筆記

一、一般介紹      STL(StandardTemplate Library),即標準模板庫,是一個具有工業強度的,高效的C++程式庫。它被容納於C++標準程式庫(C++Standard Library)中,是ANSI/ISOC+

C++學習筆記

1.struct成員預設訪問方式是public,而 class預設訪問方式是private! 2.exit函式終止程式執行會呼叫解構函式 ,abort函式終止程式不會呼叫解構函式! 3.靜態區域性變數直到程式終止時才退出! 4.通過public 函式返回 private成員的引用有可能會破壞類的封裝

5.27:cocos2d-x初探學習筆記2--重要概念及Test樣例結構()

這樣的 發生 菜單 add css 基礎 dsm 人的 添加 1.幾個重要概念 在cocos2d引擎中,有幾個概念,各自是導演。場景,布景和人物角色。 導演(CCDirector):在cocos2d-x引擎中,導演類是遊戲的組織者和領導者。導演制定規則讓遊戲內的場

JSP筆記05——生命周期

color 創建 jsp編譯 響應 init 一次 方法 blog 什麽 原始內容:https://www.tutorialspoint.com/jsp/jsp_life_cycle.htm 在這一章中,我們將討論JSP的生命周期。 理解JSP低層次功能的關鍵在於

JSP筆記04——架構

轉發 fff 如果 pri 截取 部分 blog strong 方式 Web服務器需要一個JSP引擎,即一個處理JSP頁面的容器。JSP容器負責截取JSP頁面的請求。本教程使用了內置JSP容器的Apache來支持JSP頁面的開發。 JSP容器與Web服務器配合工作以提供運

Struts2筆記01——基礎MVC架構

ima pan als 視圖 進行 tex www 執行 lsp 原始內容:https://www.tutorialspoint.com/struts_2/basic_mvc_architecture.htm Apache Struts 2是用來創建企業級Java

Struts2筆記02——Struts2 概述

混亂 truct 也有 進行 互聯網 support 核心 port 文檔 Struts2是基於MVC設計模式的一種流行、成熟的Web應用框架。 它不僅僅是Struts1的下一個版本,更是對Structs架構的一個完整重寫。 而WebWork則是以Struts框架為基礎

Angular js 過濾器 筆記自菜鳥教程

per test 筆記 ring ood filter 子集 true 貨幣格式 1、uppercase,lowercase 大小寫轉換 {{ "lower cap string" | uppercase }} // 結果:LOWER CAP STRING {{ "TA

Akka學習筆記

http lin post tar class cto iat data- 消息 Akka學習筆記系列文章:  《Akka學習筆記:ACTORS介紹》  《Akka學習筆記:Actor消息傳遞(1)》  《Akka學習筆記:Actor消息傳遞(2)》    《Akka學習筆

】Nodejs學習筆記--- 簡介及安裝Node.js開發環境

ack 目錄 javascrip 難度 時間 網站開發 clas jetbrains 常用 目錄 學習資料 簡介 安裝Node.js npm簡介 開發工具 Sublime Node.js開發環境配置 擴展:安裝多版本管理器 學習資料   1.深入淺出Node.j

使用 CJSON 在C語言中進行 JSON 的創建和解析的實例講解

orm ret ear bject str 忘記 else aid 百度 使用 CJSON 在C語言中進行 JSON 的創建和解析的實例講解 本文用代碼簡單介紹cjson的使用方法,1)創建json,從json中獲取數據。2)創建json數組和解析json數

《算法導論》讀書筆記--第1、2章課後題

秦九韶 ons 全局變量 思考 end exc ray 存在 檢查 第一章 轉自http://www.cnblogs.com/batteryhp/p/4654860.html 思考題 1-1(運行時間的比較)確定時間t內求解的問題的最大規模。 上面是網上提供的答案。

Java8學習筆記--Stream API詳解[]

有效 編程效率 實時處理 phaser 綜合 files -- bin 並發模式 為什麽要使用StreamStream 作為 Java 8 的一大亮點,它與 java.io 包裏的 InputStream 和 OutputStream 是完全不同的概念。它也不同於 StAX