使用cJSON库对JSON格式进行解析

JSON format


基本概念

JSON是JavaScript Object Notation的简称,中文含义为“JavaScript 对象表示法”,它是一种数据交换的文本格式,而不是一种编程语言

它易于阅读和编写,并且易于机械解析和生成,常在Web开发中用于数据的格式和传输


数据格式

对象

JSON 由两种数据结构组成:对象和数组。对象(object)是由键值对组成的无序集合,键是字符串,值可以是任何类型,包括对象和数组。对象由一对花括号{ }包围,键和值之间用冒号:分隔。键值对之间用逗号,分隔。

//是一个JSON格式的对象,对象中有3个键值对 ,键的名称:“name”  “age”   “score”
{
//键值对
“name” 	:  “lmx”,     //值的类型:字符串
“age” 	:  29,		 //值的类型:整型

“score”	:[			 //值的类型:数组 ,数组中有1个元素,元素类型是对象
            {
                //对象中包含2个键值对
“xxx”: 85.5,  //值的类型是浮点型
“xxx”: 92
}
]
}


数组

JSON 由两种数据结构组成:对象和数组。数组(array)是值(value)的有序集合,每个值可以是任何类型,包括对象和数组。数组由一对方括号[ ]包围,值之间用逗号,分隔。

[ "apple",  "banana",  "orange"] 

在上面的例子中,可以看到数组包含三个字符串元素,分别是:"apple"、"banana"和"orange"。


解析方法

一般嵌入式开发中可以使用cJSON库对JSON格式进行解析,cJSON库是基于C语言的一个开源项目,github下载地址:https://github.com/DaveGamble/cJSON

Untitled

cJSON库主要的文件有两个:一个是cJSON.c 一个是cJSON.h。使用时在工程中包含头文件即可,在cJSON.h头文件中有一个用于解析JSON格式的结构体,如下:

Untitled

解析JSON流程

  1. 想要解析JSON格式,前提是得到存储了JSON数据的字符串,一般就是HTTP的请求或者响应的时候,绝大多数的情况都是服务器响应的数据为JSON格式。

    Untitled

  2. 需要把存储了JSON数据的字符串进行转换,转换JSON格式,此时可以通过cJSON库中README.md来分析,可以知道调用 cJSON_Parse() 进行解析,该函数的返回值就是cJSON格式的数据

    Untitled

  3. 如果得到了转换成功的JSON格式的字符串,可以对该字符串进行调试输出,可以选择调用cJSON_Print(),该函数的返回值就是存储了JSON格式的字符串,如下:

    Untitled

  4. 如果输出结果没有问题,则可以开始对JSON数据进行解析,其中可以先从JSON对象中获得某个键的值,相当于对某个键值对进行解析,注意:如果键值对的值的类型不是字符串、整型、浮点型,则需要继续对键值对进行解析。否则,可以直接输出键值对的内容,利用JSON对象的结构体指针cJSON *的成员valuestring、valueint、valuedouble。

    Untitled

  5. 如果键值对的类型不是基本类型,而是对象或者数组,则需要继续解析,此时分为两种情况,第一种是情况:键值对的值的类型是数组,此时可以选择调用cJSON_GetArraySize()函数,该函数的作用是获取数组中的元素的数量。另外,可以选择调用cJSON_GetArrayItem()函数,可以获取数组中的元素,如果数组的元素类型是对象,则可以选择调用cJSON_GetObjectItem()函数对对象进行解析

    Untitled


构造JSON流程

  1. 如果打算构造JSON格式,则需要首先创建一个JSON顶层对象,需要调用cJSON_CreateObject(),也就是该函数可以创建对象,其实就是构造一对{ }。

    Untitled

案例

可以选择继续调用cJSON_CreateObject()来创建新的小对象,此时可以选择向小对象中添加键值对,添加键值对的前提是构造键值对,需要先把键值对的值添加到创建的对象中,再把小对象添加到其他对象中,具有嵌套关系。根据键值对的值的类型,可以选择调用。


Untitled

//示例:
{
   "action":"mode_set",
   "mode":1,
   "datalist":
            {
                "username":"admin",
                "password":"admin" 
            }
   "register":
             ["{
                "status":"0",
                "msg":"Success." 
             }"]
}
 
//组数据:
cJSON *JsRegisterArr = cJSON_CreateArray();
cJSON *JsRegisterObj = cJSON_CreateObject();
cJSON_AddItemToObject(JsData, "register", JsRegisterArr);
cJSON_AddItemToArray(JsRegisterArr, JsRegisterObj);
cJSON_AddStringToObject(JsRegisterObj, "status", "0");
cJSON_AddStringToObject(JsRegisterObj, "msg", "Success");
 
//解析数据:
cJSON *JsRegisterArr = NULL;
cJSON *JsRegisterObj = NULL;
cJSON *pValue = NULL;
UINT4  u4DataSize = 0; 
JsRegisterArr = cJSON_GetObjectItem(JsData, "register");
u4DataSize = cJSON_GetArraySize(JsRegisterArr);
for (UINT4 u4Index = 0; u4Index < u4DataSize; u4Index ++)
{
   JsRegisterObj = cJSON_GetArrayItem(JsRegisterArr, u4Index)
   pValue = cJSON_GetObjectItem(JsRegisterObj, "status");
   printf("status : %s \r\n", pValue->valuestring);
   pValue = cJSON_GetObjectItem(JsRegisterObj, "msg");
   printf("msg : %s \r\n", pValue->valuestring);
}

//以下函数调用时都会申请内存,如果不释放内存会造成内存泄露:
cJSON_Parse();
cJSON_CreateObject();
cJSON_CreateArray();
cJSON_Print();
cJSON_PrintUnformatted();
 
//释放内存:
cJSON_Delete();
cJSON_free();
 
//用法解释:
//1.调用cJSON_Parse,cJSON_CreateObject,cJSON_CreateArray时,使用cJSON_Delete释放内存,
//比如JsData = cJSON_CreateObject(), DataListArr = cJSON_CreateArray();cJSON_AddItemToArray(DataListArr, JsData);
//这种情况只要cJSON_Delete(JsData), 这样也会同时释放DataListArr的内存。
//2.如果是调用cJSON_Print,cJSON_PrintUnformatted时,则使用cJSON_free();
 
//建议:
//因为涉及申请内存及释放内存,所以在每次creat一个cJSON后,使用前都要判空。
cJSON *JsData = NULL;
JsData = cJSON_CreateObject();
if (JsData == NULL)
   return FAILURE;
   
posted @ 2024-06-13 00:48  晖_IL  阅读(42)  评论(0编辑  收藏  举报