cJSON源码下载:https://sourceforge.net/projects/cjson/
1.先来了解什么是JSON。
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation);
JSON 是轻量级的文本数据交换格式;
JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON;
JSON 具有自我描述性,更易理解。
2.JSON语法规则
JSON 语法是 JavaScript 对象表示语法的子集。
数据在名称/值对中;
数据由逗号分隔;
大括号保存对象;
中括号保存数组;
JSON数据的书写格式是:名称/值对
名称包括字段名称,名称在双引号中,名称后面跟一个冒号,然后是值。
例如:
"name":"xiaoming"
3.JSON值
JSON值可以包括以下几类:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在中括号中)
对象(在大括号中)
null
JSON数字可以在整型或浮点型,例如:
{”age":17}
JSON对象需要写在大括号中,一个JSON对象可以包含多个名称/值对。名称/值对之间用逗号分隔,例如:
{"name":"小明","age":18}
JSON数组写在中括号中,一个数组可以包含多个对象,例如:
[{"name":"小明","age":17},{"name":"小红","age":18}]
JSON 布尔值可以是 true 或者 false:
{ "flag":true }
JSON 可以设置 null 值
{ "pointer":null }
嵌入式开发中,在客户端和服务器端通信的时候,可能会用到JSON来封装数据,这时候就需要借助轻量的cJSON库了,cJSON库通常包括cJSON.c和cJSON.h这两个文件,我们封装数据的时候,就可以直接借助其进行封装就好了,只需要在我们自己的源文件中包含"cJSON.h"这个文件,以及在编译时按如下方式,例如编译x.c文件时,
gcc x.c cJSON.c -lm
-lm指定链接libm库。
下面是用cJSON进行封包的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "cJSON.h"
void cjson_parse(cJSON *root);
cJSON *cjson_pkg(void);
int main()
{
cJSON *root = cjson_pkg();
cjson_parse(root);
return 0;
}
/*cJSON的封装*/
cJSON *cjson_pkg(void)
{
printf("%s\n",buf);
cJSON *root = cJSON_CreateObject();
if (NULL == root) {
return NULL;
}
cJSON_AddStringToObject(root, "cmd", "write");
cJSON *data = cJSON_CreateObject();
if (NULL == data) {
goto err1;
}
cJSON_AddNumberToObject(data, "sn","fl2440001");
cJSON_AddStringToObject(data, "mac", "aa:bb:cc:dd:ee:ff");
cJSON_AddItemToObject(root, "data", data);
return root;
err1:
cJSON_Delete(root);
return NULL;
}
/*cJSON的解析*/
void cjson_parse(cJSON *root)
{
if (NULL == root)
{
return;
}
//将json包转为字符串显示
char *str = cJSON_PrintUnformatted(root);
printf("str: \n%s\n", str);
cJSON_Delete(root);
cJSON *sys_root = cJSON_Parse(str);
if (NULL == sys_root) {
goto err1;
}
cJSON *cmd = cJSON_GetObjectItem(sys_root, "cmd");
if (NULL == cmd) {
goto err2;
}
char *cmd_value = cmd->valuestring;
cJSON *data = cJSON_GetObjectItem(sys_root, "data");
if (NULL == data) {
goto err2;
}
cJSON *sn = cJSON_GetObjectItem(data, "sn");
if (NULL == sn) {
goto err2;
}
char *sn_value = sn->valuestring;
cJSON *mac = cJSON_GetObjectItem(data, "mac");
if (NULL == mac) {
goto err2;
}
char *mac_value = mac->valuestring;
printf("cmd = %s, sn = %s, mac = %s\n", cmd_value, sn_value, mac_value);
err2:
cJSON_Delete(sys_root);
err1:
free(str);
return ;
}
上述代码实现了将数据按照cJSON格式进行封装和解析,需要注意的是,通过函数cJSON_PrintUnformatted()返回的字符串需要手动free,通过函数cJSON_CreateObiect()返回的数据需要在这些数据不再使用时调用cJSON_Delete()释放。
三、cJSON使用数组封装合解封装
cJSON名称值对中,其值可以是对象,也可以是数组,下面的代码是使用cJSON格式的数组来封装数据合解析数据。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "cJSON.h"
void cjson_array_parse(cJSON *root);
cJSON *cjson_pkg(void);
int main()
{
cJSON *root = cjson_pkg();
cjson_array_parse(root);
return 0;
}
/* cJSON的封装*/
cJSON *cjson_pkg(void)
{
char buf[20];
int i;
printf("%s\n",buf);
cJSON *root = cJSON_CreateObject();
if (NULL == root)
{
return NULL;
}
cJSON_AddStringToObject(root, "cmd", "write");
cJSON *data = cJSON_CreateObject();
if (NULL == data) {
goto err1;
}
cJSON_AddItemToObject(root, "data", data);
cJSON *rows = cJSON_CreateArray();
if(NULL == rows)
{
goto err1;
}
cJSON_AddItemToObject(data,"rows",rows);
for(i = 0;i < 2; i++)
{
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "user %d", i);
cJSON *row = cJSON_CreateObject();
if(NULL == row)
{
goto err1;
}
cJSON_AddItemToArray(rows, row);
cJSON_AddStringToObject(row, "user", buf);
cJSON_AddStringToObject(row, "pwd", "abcdefg");
}
return root;
err1:
cJSON_Delete(root);
return NULL;
}
/* cJSON的解析*/
void cjson_array_parse(cJSON *root)
{
if(NULL == root)
{
return;
}
char *str1 = cJSON_PrintUnformatted(root);
printf("str1: %s\n", str1);
cJSON_Delete(root);
cJSON *sys_root = cJSON_Parse(str1);
if(NULL == sys_root){
goto err1;
}
cJSON *cmd = cJSON_GetObjectItem(sys_root, "cmd");
if(NULL == cmd)
{
goto err2;
}
char *cmd_value = cmd->valuestring;
cJSON *data = cJSON_GetObjectItem(root, "data");
if(NULL == data)
{
goto err2;
}
cJSON *rows = cJSON_GetObjectItem(data, "rows");
if(NULL == rows)
{
goto err2;
}
int array_cnt = cJSON_GetArraySize(rows);
printf("cmd = %s, array count = %d\n", cmd_value,array_cnt);
int i;
for (i = 0; i < array_cnt; i ++)
{
cJSON *row = cJSON_GetArrayItem(rows, i);
if (NULL == row)
{
goto err2;
}
cJSON *user = cJSON_GetObjectItem(row, "user");
if (NULL == user)
{
goto err2;
}
cJSON *pwd = cJSON_GetObjectItem(row, "pwd");
if (NULL == pwd)
{
goto err2;
}
printf("user: %s, pwd: %s\r\n", user->valuestring, pwd->valuestring);
}
err2:
cJSON_Delete(sys_root);
err1:
free(str1);
return ;
}