JSON 是一种轻量级的数据交换格式。它采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在C语言中一般使用libcjson库进行json数据的解析与创建,下面会使用两个例程分别介绍如何解析和创建json数据。
备注:手动创建json数据可通过一些在线的json数据校验工具。可准确检查出json的语法错误,还可以快速的对json数据进行压缩和转义,便于C程序的调试。见:http://www.bejson.com/
1、json数据解析
使用到的接口有:
cJSON_Parse():解析json字符串;
cJSON_GetObjectItem():获取一个json项目;
cJSON_GetArrayItem():获取一个json数组;
cJSON_Print():转换json数据为字符串;
cJSON_Delete():销毁json数据,注意通过cJSON_Parse()创建的json数据中分配了堆存储,必须通过cJSON_Delete()注销才能释放空间;
待解析的数据如下:
{
"school": "gaoqi",
"type": "aa",
"student_num": 120,
"student_max": 200,
"grade_info": {
"grade_num": 3,
"grade_list": [{
"grade_level": 7,
"people": 40,
"class_info": {
"class_num": 2,
"class_list": [{
"class_id": 1,
"people": 18,
"score_avr": 72.5
},
{
"class_id": 2,
"people": 22,
"score_avr": 72.5
}
]
}
},
{
"grade_level": 8,
"people": 60,
"class_info": {
"class_num": 3,
"class_list": [{
"class_id": 1,
"people": 32,
"score_avr": 83.3
},
{
"class_id": 2,
"people": 18,
"score_avr": 72.5
},
{
"class_id": 3,
"people": 10,
"score_avr": 71.2
}
]
}
},
{
"grade_level": 9,
"people": 21,
"class_info": {
"class_num": 1,
"class_list": [{
"class_id": 1,
"people": 21,
"score_avr": 82.9
}]
}
}
]
}
}
解析例程cjson_test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
const char pBuf[] = "{\"school\":\"gaoqi\",\"type\":\"aa\",\"student_num\":120,\"student_max\":200,\"grade_info\":{\"grade_num\":3,\"grade_list\":[{\"grade_level\":7,\"people\":40,\"class_info\":{\"class_num\":2,\"class_list\":[{\"class_id\":1,\"people\":18,\"score_avr\":72.5},{\"class_id\":2,\"people\":22,\"score_avr\":72.5}]}},{\"grade_level\":8,\"people\":60,\"class_info\":{\"class_num\":3,\"class_list\":[{\"class_id\":1,\"people\":32,\"score_avr\":83.3},{\"class_id\":2,\"people\":18,\"score_avr\":72.5},{\"class_id\":3,\"people\":10,\"score_avr\":71.2}]}},{\"grade_level\":9,\"people\":21,\"class_info\":{\"class_num\":1,\"class_list\":[{\"class_id\":1,\"people\":21,\"score_avr\":82.9}]}}]}}";
int cjsonToValue (cJSON* pMap, char *pcKey, void *pValue)
{
int iRet = -1;
cJSON* pNode = NULL;
if (!pMap || !pcKey || !pValue) {
return (PX_ERROR);
}
/*
* 根据 key 值获取一个项目
*/
if ((pNode = cJSON_GetObjectItem(pMap, pcKey))) {
switch (pNode->type) {
case cJSON_Number: /* 数值类型使用 double 存储 */
*(double *)pValue = pNode->valuedouble;
break;
case cJSON_String: /* 字符串类型 */
strcpy(pValue, pNode->valuestring);
break;
case cJSON_Object: /* 一个 cjson 子项目 */
strcpy(pValue, cJSON_Print(pNode));
break;
default:
break;
}
iRet = 0;
}
return (iRet);
}
int main (int argc, char **argv)
{
int i, j;
cJSON *pRoot = NULL;
cJSON *pGradeInfo = NULL;
cJSON *pGradeList = NULL;
char cString[100] = {0};
double dNum;
double dGradeNum;
pRoot = cJSON_Parse(pBuf); /* 解析 cJSON 字符串 */
if (pRoot == NULL) {
printf("cjson parse error:%s\n", cJSON_GetErrorPtr());
goto __end;
}
/*
* 获取学校信息
*/
if (cjsonToValue(pRoot, "school", cString) || !strlen(cString)) {
printf("cjson get school error\n");
goto __end;
}
printf("school:%s\n", cString);
if (cjsonToValue(pRoot, "type", cString) || !strlen(cString)) {
printf("cjson get type error\n");
goto __end;
}
printf("type:%s\n", cString);
if (cjsonToValue(pRoot, "student_num", &dNum)) {
printf("cjson get student_num error\n");
goto __end;
}
printf("student_num:%d\n", (int)dNum);
if (cjsonToValue(pRoot, "student_max", &dNum)) {
printf("cjson get student_max error\n");
goto __end;
}
printf("student_max:%d\n", (int)dNum);
/*
* 获取年级信息
*/
pGradeInfo = cJSON_GetObjectItem(pRoot, "grade_info");
if (pRoot == NULL) {
printf("cjson parse grade_info error:%s\n", cJSON_GetErrorPtr());
goto __end;
}
if (cjsonToValue(pGradeInfo, "grade_num", &dGradeNum)) {
printf("cjson get grade_num error\n");
goto __end;
}
printf("grade_num:%d\n", (int)dGradeNum);
pGradeList = cJSON_GetObjectItem(pGradeInfo, "grade_list");
if (pGradeList == NULL) {
printf("cjson get grade_list error\n");
goto __end;
}
/*
* 循环读取年级数组信息
*/
for (i = 0; i < (int)dGradeNum; i++) {
cJSON *pGradeItem = NULL;
cJSON *pClassInfo = NULL;
cJSON *pClassList = NULL;
double dClassNum;
pGradeItem = cJSON_GetArrayItem(pGradeList, i);
if (pGradeItem == NULL) {
printf("cjson get grade item error\n");
goto __end;
}
if (cjsonToValue(pGradeItem, "grade_level", &dNum)) {
printf("cjson get grade_level error:%s\n", cJSON_GetErrorPtr());
goto __end;
}
printf("\tgrade_level:%d\n", (int)dNum);
if (cjsonToValue(pGradeItem, "people", &dNum)) {
printf("cjson get people error\n");
goto __end;
}
printf("\tpeople:%d\n", (int)dNum);
/*
* 获取班级信息
*/
pClassInfo = cJSON_GetObjectItem(pGradeItem, "class_info");
if (pClassInfo == NULL) {
printf("cjson parse class_info error:%s\n", cJSON_GetErrorPtr());
goto __end;
}
if (cjsonToValue(pClassInfo, "class_num", &dClassNum)) {
printf("cjson get class_num error\n");
goto __end;
}
printf("\tclass_num:%d\n", (int)dClassNum);
pClassList = cJSON_GetObjectItem(pClassInfo, "class_list");
if (pClassList == NULL) {
printf("cjson get class_list error\n");
goto __end;
}
for (j = 0; j < (INT)dClassNum; j++) {
cJSON *pClassItem = NULL;
pClassItem = cJSON_GetArrayItem(pClassList, j);
if (pClassItem == NULL) {
printf("cjson get class item error\n");
goto __end;
}
if (cjsonToValue(pClassItem, "class_id", &dNum)) {
printf("cjson get class_id error\n");
goto __end;
}
printf("\t\tclass_id:%d\n", (int)dNum);
if (cjsonToValue(pClassItem, "people", &dNum)) {
printf("cjson get people error\n");
goto __end;
}
printf("\t\tpeople:%d\n", (int)dNum);
if (cjsonToValue(pClassItem, "score_avr", &dNum)) {
printf("cjson get score_avr error\n");
goto __end;
}
printf("\t\tscore_avr:%0.2lf\n\n", dNum);
}
printf("\n");
}
__end:
if (pRoot) {
cJSON_Delete (pRoot); /* 销毁 */
}
return (0);
}
执行结果如下:
# /apps/cjson_test/cjson_test
school:gaoqi
type:aa
student_num:120
student_max:200
grade_num:3
grade_level:7
people:40
class_num:2
class_id:1
people:18
score_avr:72.50
class_id:2
people:22
score_avr:72.50
grade_level:8
people:60
class_num:3
class_id:1
people:32
score_avr:83.30
class_id:2
people:18
score_avr:72.50
class_id:3
people:10
score_avr:71.20
grade_level:9
people:21
class_num:1
class_id:1
people:21
score_avr:82.90
2、创建一个json结构
使用到的接口有:
cJSON_CreateObject():创建一个json数据结点;
cJSON_AddStringToObject():添加一个字符串数据;
cJSON_AddNumberToObject():添加一个数值数据;
cJSON_AddItemToObject():添加一个json项目;
cJSON_CreateArray():添加一个json数组;
cJSON_Print():转换json数据为字符串;
cJSON_Delete():销毁json数据,注意通过cJSON_Parse()创建的json数据中分配了堆存储,必须通过cJSON_Delete()注销才能释放空间;
创建json结构例程cjson_create.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
int main (int argc, char **argv)
{
cJSON *pRoot = NULL;
cJSON *pGradeInfo = NULL;
cJSON *pGradeList = NULL;
int i, j;
char *pOut;
pRoot = cJSON_CreateObject();
/*
* 添加学校信息
*/
cJSON_AddStringToObject(pRoot, "school", "shihua");
cJSON_AddStringToObject(pRoot, "type", "bb");
cJSON_AddNumberToObject(pRoot, "student_num", 120);
cJSON_AddNumberToObject(pRoot, "student_max", 200);
/*
* 添加年级信息
*/
pGradeInfo = cJSON_CreateObject();
cJSON_AddItemToObject(pRoot, "grade_info", pGradeInfo);
cJSON_AddNumberToObject(pGradeInfo, "grade_num", 3);
pGradeList = cJSON_CreateArray();
cJSON_AddItemToObject(pGradeInfo, "grade_list", pGradeList);
for (i = 0; i < 3; i++) {
cJSON *pClassInfo = NULL;
cJSON *pClassList = NULL;
cJSON *pItem = cJSON_CreateObject();
cJSON_AddItemToArray(pGradeList, pItem);
cJSON_AddNumberToObject(pItem, "grade_level", 7 + i);
cJSON_AddNumberToObject(pItem, "people", 40);
/*
* 添加班级信息
*/
pClassInfo = cJSON_CreateObject();
cJSON_AddItemToObject(pItem, "class_info", pClassInfo);
cJSON_AddNumberToObject(pClassInfo, "class_num", 2);
pClassList = cJSON_CreateArray();
cJSON_AddItemToObject(pClassInfo, "grade_list", pClassList);
for (j = 0; j < 2; j++) {
cJSON *pItem = cJSON_CreateObject();
cJSON_AddItemToArray(pClassList, pItem);
cJSON_AddNumberToObject(pItem, "class_id", j + 1);
cJSON_AddNumberToObject(pItem, "people", 20);
cJSON_AddNumberToObject(pItem, "score_avr", 72.23);
}
}
pOut = cJSON_Print(pRoot);
printf("%s\n", pOut);
cJSON_Delete(pRoot);
return (0);
}
执行结果如下:
# /apps/cjson_create/cjson_create
{
"school": "shihua",
"type": "bb",
"student_num": 120,
"student_max": 200,
"grade_info": {
"grade_num": 3,
"grade_list": [{
"grade_level": 7,
"people": 40,
"class_info": {
"class_num": 2,
"grade_list": [{
"class_id": 1,
"people": 20,
"score_avr": 72.23
}, {
"class_id": 2,
"people": 20,
"score_avr": 72.23
}]
}
}, {
"grade_level": 8,
"people": 40,
"class_info": {
"class_num": 2,
"grade_list": [{
"class_id": 1,
"people": 20,
"score_avr": 72.23
}, {
"class_id": 2,
"people": 20,
"score_avr": 72.23
}]
}
}, {
"grade_level": 9,
"people": 40,
"class_info": {
"class_num": 2,
"grade_list": [{
"class_id": 1,
"people": 20,
"score_avr": 72.23
}, {
"class_id": 2,
"people": 20,
"score_avr": 72.23
}]
}
}]
}
}