cJSON是一个c语言编写的构建和解析json格式数据的库
源码在这里下载 https://github.com/DaveGamble/cJSON
主要就两个文件cJSON.c和cJSON.h,直接一起链接进来就可以了
创建json
这里面最重要的一个结构为cJSON
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
cJSON对象成员
prev,节点前趋指针,指向前一个cJSON节点
next,节点后继指针,指向后一个cJSON节点
child,当一个键值对key,value中,value为Array或Object时,child才有指向,否则child=NULL
下面的例子里,child是这样的指向
value为object(type=cJSON_Object)时,child指向object中第一个元素
score->type=cJSON_Object;
score->child =Chinese; score->next=friend;
Chinese->next=English; Chinese->child=NULL;
English->next=Math;
当value为Array(type=CJSON_Array)时,child指向此Array中的第一个元素
friend->type=cJSON_Array;
friend->child=friend1;
friend1->next=friend2;
type,代表key,value键值对中value的类型
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
valuestring,当类型为cJSON_String 或cJSON_Raw时,value的值,type不符时为NULL
valueint,当类型为cJSON_Number时,value的值
valuedouble,当类型为cJSON_NUmber时,value的值(主要用这个)
string, 代表key,value键值对中key的值
cJSON实际上是一个双向链表,还是举个例子好了
{
"name": "luoc",
"age": 16,
"sex": "male",
"student": true,
"score": {
"Chinese": 92,
"English": 76,
"Math": 83,
"Physical": 88
},
"friend": [{
"name": "chenx",
"sex": "female",
"age": 15
}, {
"name": "yanl",
"sex": "male",
"age": 16
}, {
"name": "xiax",
"sex": "male",
"age": 16
}]
}
如果要创建这么一个json格式的文件,需要6个cJSON结构(有几对括号,就需要几个结构)
代码如下
#include <stdio.h>
#include <stdbool.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
cJSON *item = NULL;
cJSON *score = NULL;
cJSON *friend = NULL;
cJSON *friend1 = NULL;
cJSON *friend2 = NULL;
cJSON *friend3 = NULL;
// 最外层的大括号
item = cJSON_CreateObject();
cJSON_AddStringToObject(item, "name", "luoc");
cJSON_AddStringToObject(item, "sex", "male");
cJSON_AddNumberToObject(item, "age", 16);
cJSON_AddBoolToObject(item, "student", true);
// score
score = cJSON_CreateObject();
cJSON_AddNumberToObject(score, "Chinese", 92);
cJSON_AddNumberToObject(score, "English", 76);
cJSON_AddNumberToObject(score, "Math", 83);
cJSON_AddNumberToObject(score, "Physical", 88);
cJSON_AddItemToObject(item, "score", score);
// friend
friend = cJSON_CreateArray();
cJSON_AddItemToObject(item, "friend", friend);
// friend1
friend1 = cJSON_CreateObject();
cJSON_AddStringToObject(friend1, "name", "chenx");
cJSON_AddStringToObject(friend1, "sex", "female");
cJSON_AddNumberToObject(friend1, "age", 15);
// friend2
friend2 = cJSON_CreateObject();
cJSON_AddStringToObject(friend2, "name", "yanl");
cJSON_AddStringToObject(friend2, "sex", "male");
cJSON_AddNumberToObject(friend2, "age", 16);
// friend3
friend3 = cJSON_CreateObject();
cJSON_AddStringToObject(friend3, "name", "xiax");
cJSON_AddStringToObject(friend3, "sex", "male");
cJSON_AddNumberToObject(friend3, "age", 16);
cJSON_AddItemToArray(friend, friend1);
cJSON_AddItemToArray(friend, friend2);
cJSON_AddItemToArray(friend, friend3);
// printf("%s\n\n", cJSON_Print(item));
FILE *fp = fopen("my.json", "a+");
if(fp)
fprintf(fp, "%s", cJSON_Print(item));
fclose(fp);
cJSON_Delete(item);
return 0;
}
解析json
还是解析上面的json串吧,直接上代码
#include <stdio.h>
#include "cJSON.h"
int main(int argc, char *argv[])
{
char *str = "{ \
\"name\": \"luoc\", \
\"age\": 16, \
\"sex\": \"male\", \
\"student\": true, \
\"score\": { \
\"Chinese\": 92, \
\"English\": 76, \
\"Math\": 83, \
\"Physical\": 88 \
}, \
\"friend\": [{ \
\"name\": \"chenx\", \
\"sex\": \"female\", \
\"age\": 15 \
}, { \
\"name\": \"yanl\", \
\"sex\": \"male\", \
\"age\": 16 \
}, { \
\"name\": \"xiax\", \
\"sex\": \"male\", \
\"age\": 16 \
}] \
}";
cJSON *item = cJSON_Parse(str);
if(item == NULL)
{
printf("Parse error\n");
goto end;
}
cJSON *name = cJSON_GetObjectItem(item, "name");
if(name == NULL)
{
printf("No item 'name'\n");
goto end;
}
if(cJSON_IsString(name))
printf("name=[%s]\n", name->valuestring);
cJSON *score = cJSON_GetObjectItem(item, "score");
cJSON *score_print = cJSON_Print(score);
printf("score=[%s]\n", score_print);
// cJSON_Print会malloc空间,需要free
cJSON_free(score_print);
cJSON *friend = cJSON_GetObjectItem(item, "friend");
printf("friend is a array=[%s]\n", cJSON_IsArray(friend) ? "true" : "false");
int size = cJSON_GetArraySize(friend);
printf("friend count =[%d]\n", size);
int i = 0;
cJSON *curr = NULL;
curr = friend->child;
for(i = 0; i < size; i++)
{
cJSON *name = cJSON_GetObjectItem(curr, "name");
printf("friend%d is named [%s]\n", i, name->valuestring);
curr = curr->next;
}
end:
if(item)
cJSON_Delete(item);
return 0;
}
主要是 cJSON_Parse,解析后返回的cJSON对象,是这个双向链表的head指针然后可以通过cJSON_GetObjectItem来一个个得获取最外层的节点,根据type来判断节点value类型
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
不同节点,取自己需要的value就行了