JSON详解
本文部分借鉴 阿阿阿阿阿阿鑫 的博客,特此说明。
https://blog.csdn.net/fengxinlinux/article/details/53121287
一.JSON格式简述
JSON(JavaScriptObject Notation, JS 对象标记) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
cJSON从名字可知,整个项目都是以极标准的C来写的,意思说,可以跨各种平台使用了。cJSON是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。
二.cJSON结构体
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
说明1.cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。
说明2.type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array,Object。若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。若是String类型的,则valuestring中存储着值,可以访问valuestring得到值
说明3.string中存放的是这个节点的名字,可理解为key的名称。
说明4.cJSON作为Json格式的解析库,其主要功能无非就是构建和解析Json格式了,用途就是一端将要发送的数据已cjson形式封装,然后发送,另一端收到此数据后,还是按cjson形式解析,就得到想要的数据了。
三.封装为JSON格式
3.1 创建一个对象,并向这个对象里添加字符串和整型键值
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"
int main()
{
cJSON * usr;
cJSON *arry;
usr=cJSON_CreateObject(); //创建根数据对象
cJSON_AddStringToObject(usr,"name","fengxin"); //加入键值,加字符串
cJSON_AddStringToObject(usr,"passwd","123");
cJSON_AddNumberToObject(usr,"num",1); //加整数
char *out = cJSON_Print(usr); //将json形式打印成正常字符串形式
printf("%s\n",out);
// 释放内存
cJSON_Delete(usr);
free(out);
}
运行结果:
{
"name": "fengxin",
"passwd": "123",
"num": 1
}
API说明:
1.cJSON_CreateObject函数可创建一个根数据项,之后便可向该根数据项中添加string或int等内容,返回的是一个 cJSON的指针,注意,在这个指针用完了以后,需要手工调用 cJSON_Delete(root); 进行内存回收。因为内部malloc申请了内存
2.cJSON_AddNumberToObject向节点中添加子节点,例如此处添加name节点,节点值为字符串"fengxin"
3.需要注意的是 json 格式的数据,虽然也是一个字符串的样子,但这个时候还是无法当成普通的字符串进行使用,需要调用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);来将json对象转换成普通的字符串,并且都是以该json对象的根为基点。两个API的区别即是:一个是没有格式的:也就是转换出的字符串中间不会有"\n" "\t"之类的东西存在,而cJSON_Print(root);打印出来是人看起来很舒服的格式。
4.因为函数内部封装有malloc函数,所以使用free函数释放被out占用的内存空间
3.2 创建一个数组,并向数组添加一个字符串和一个数字:
int create_js(void)
{
cJSON *root, *js_body;
root = cJSON_CreateArray();
cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
cJSON_AddItemToArray(root, cJSON_CreateNumber(10));
{
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);
return 0;
}
int main(int argc, char **argv)
{
create_js();
return 0;
}
运行结果:
["Hello world",10]
3.3 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字:
int create_js(void)
{
cJSON *root, *js_body, *js_list;
root = cJSON_CreateObject();
cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray());
cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject());
cJSON_AddStringToObject(js_list,"name","fengxin");
cJSON_AddNumberToObject(js_list,"status",100);
{
char *s = cJSON_PrintUnformatted(root);
if(s){
printf(" %s \n",s);
free(s);
}
}
if(root)
cJSON_Delete(root);
return 0;
}
int main(int argc, char **argv)
{
create_js();
return 0;
}
运行结果:
{"body":[{"name":"fengxin","status":100}]}
四.解析JSON格式包得到数据
4.1 首先将普通的json串处理成json对象
cJSON *root;
root = cJSON_Parse(js_string);
4.2 取关键字之无父层次,但如果关键字还有父层或者祖层,那就需要先从父层开拿,剥洋葱一样:
out={\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"cJSON.h"
int main()
{
cJSON *json,*json_name,*json_passwd,*json_num;
char* out="{\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}";
json = cJSON_Parse(out); //解析成json形式
json_name = cJSON_GetObjectItem( json , "name" ); //获取键值内容
json_passwd = cJSON_GetObjectItem( json , "passwd" );
json_num = cJSON_GetObjectItem( json , "num" );
printf("name:%s,passwd:%s,num:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);
cJSON_Delete(json); //释放内存
free(out);
}
运行结果:
name:fengxin,passwd:123,num:1
4.3 取关键字之有父层次
out={\"list\":{\"name\":\"hahaha\"}}
char *s = "{\"list\":{\"name\":\"hahaha\"}}";
cJSON *root = cJSON_Parse(s); //解析成json形式
cJSON *js_list = cJSON_GetObjectItem(root, "list");//获取键值(节点值)
cJSON *name = cJSON_GetObjectItem(js_list, "name");
printf("name is %s\n",name->valuestring);
if(root){
cJSON_Delete(root);
return 0;
}
结果:
name is xiao hong