目的:
对字符串进行处理一直是c语言的一个弱项,如果要形成某种格式的数据,要一个一个地去规范化格式,是很恼火的,因此需要使用工具去做这种字符串格式的事。当需要的数据格式为json时,我们可以使用现有的cJson来处理,以达到形成json,解析json的目的。
编译时注意事项:
在linux下编译cJSON文件,需要链接libm库,如 gcc *.c -l m
一.什么是json
json就是键值对的集合。而键值对,则是一种一对一关系的结构: name: value。
最简单的集合里面是这种结构:
{
"name1": "value1",
"name2": "value2",
"name3": "value3",
......
}
由于数据间有层级结构,如学科里面有语文、数学、英语等结构,人们希望通过学科(subject)就能快速索引到关注的内容(语文、英语、数学),所以格式变成了这样。
{
"name1": "value1",
"name2": "value2",
"name3": "value3",
"subject": {
"Math":"98",
"Chinese","99",
"English","60"
}
}
在此我们看到了即使复杂一点的json结构,也是键值结构: name: value ,不同的只是这个value变成了一个集合。
有些数据是高度相似的,如你有很多银行卡,建行的,农行的,交行的,这些银行卡本身也是一个集合(总要有帐号、密码之类的吧),我们习惯用数组去描述它。
{
"name1": "value1",
"name2": "value2",
"subject": {
"Math":"98",
"Chinese","99",
"English","60"
}
"bankcard": [
{
"bankname": "CCB",
"bankcard": "123456",
"bankpwd": "543254"
}, {
"bankname": "ABC",
"bankcard": "23456",
"bankpwd": "543254"
}
]
}
这时候我们能通过bandcard去索引到银行卡们。在此:bandcard的value变成了一个数组。而数组由数个结构相似的集合组成。
这之后的json结构,千变不离其宗,都是这种类似的格式,无非就是多了些层次。
2.3 代码注意事项
1.
cJSON_CreateObject(),cJSON_CreateArray() 函数申请了内存空间,需调用 cJSON_Delete()函数去释放内存。
2.如:
cJSON *pJsonRoot = cJSON_CreateObject();
cJSON *pJsonSubject = cJSON_CreateObject();
cJSON_AddItemToObject(pJsonRoot,"subject",pJsonSubject);
即pJsonRoot包含了pJsonSubject,此时只需要 cJSON_Delete(pJsonRoot);pJsonSubject对象会被随之释放掉。
3.
char* out = cJSON_Print(pJsonRoot);
必须调用free(out)去释放内存。
三.解析json
3.1目标:
1.在事先知道json格式的情况下(一般是约定好的格式),通过name去获取其value
2.解析未知的json,取出所有的name 和value
代码以上述组成的json来去解析。
3.2 代码:
3.3 代码注意事项
使用 cJSON* pRoot = cJSON_Parse(data),结束后需要 cJSON_Delete(pRoot),否则会内存泄漏
对字符串进行处理一直是c语言的一个弱项,如果要形成某种格式的数据,要一个一个地去规范化格式,是很恼火的,因此需要使用工具去做这种字符串格式的事。当需要的数据格式为json时,我们可以使用现有的cJson来处理,以达到形成json,解析json的目的。
编译时注意事项:
在linux下编译cJSON文件,需要链接libm库,如 gcc *.c -l m
一.什么是json
json就是键值对的集合。而键值对,则是一种一对一关系的结构: name: value。
最简单的集合里面是这种结构:
{
"name1": "value1",
"name2": "value2",
"name3": "value3",
......
}
由于数据间有层级结构,如学科里面有语文、数学、英语等结构,人们希望通过学科(subject)就能快速索引到关注的内容(语文、英语、数学),所以格式变成了这样。
{
"name1": "value1",
"name2": "value2",
"name3": "value3",
"subject": {
"Math":"98",
"Chinese","99",
"English","60"
}
}
在此我们看到了即使复杂一点的json结构,也是键值结构: name: value ,不同的只是这个value变成了一个集合。
有些数据是高度相似的,如你有很多银行卡,建行的,农行的,交行的,这些银行卡本身也是一个集合(总要有帐号、密码之类的吧),我们习惯用数组去描述它。
{
"name1": "value1",
"name2": "value2",
"subject": {
"Math":"98",
"Chinese","99",
"English","60"
}
"bankcard": [
{
"bankname": "CCB",
"bankcard": "123456",
"bankpwd": "543254"
}, {
"bankname": "ABC",
"bankcard": "23456",
"bankpwd": "543254"
}
]
}
这时候我们能通过bandcard去索引到银行卡们。在此:bandcard的value变成了一个数组。而数组由数个结构相似的集合组成。
这之后的json结构,千变不离其宗,都是这种类似的格式,无非就是多了些层次。
二.创建json数据:
2.1 创建目标:形成以下json格式
{
"name": "darren",
"age": "25",
"subject": {
"math": "100",
"Chinese": "98"
},
"bankcard": [
{
"bankname": "CCB",
"bankcard": "123456",
"bankpwd": "543254"
}, {
"bankname": "ABC",
"bankcard": "23456",
"bankpwd": "543254"
}
]
}
2.2 以下为创建的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
int create_json(char* ret)
{
//创建根对象
cJSON *pJsonRoot = cJSON_CreateObject();
if( NULL == pJsonRoot )
{
printf("make pJsonRoot fail\n");
return -1;
}
//创建学科对象
cJSON *pJsonSubject = cJSON_CreateObject();
if( NULL == pJsonSubject )
{
printf("make pJsonSubject fail\n");
cJSON_Delete(pJsonRoot);
return -2;
}
//创建银行卡数组对象
cJSON *pJsonBankcard = cJSON_CreateArray();
if( NULL == pJsonBankcard )
{
printf("make pJsonBankcard fail\n");
cJSON_Delete(pJsonRoot);
cJSON_Delete(pJsonSubject);
return -3;
}
//创建建行卡对象
cJSON *pJsonCcb = cJSON_CreateObject();
if( NULL == pJsonCcb )
{
printf("make pJsonSubject fail\n");
cJSON_Delete(pJsonRoot);
cJSON_Delete(pJsonSubject);
cJSON_Delete(pJsonBankcard);
return -4;
}
//创建农行卡对象
cJSON *pJsonAbc = cJSON_CreateObject();
if( NULL == pJsonAbc )
{
printf("make pJsonSubject fail\n");
cJSON_Delete(pJsonRoot);
cJSON_Delete(pJsonSubject);
cJSON_Delete(pJsonBankcard);
cJSON_Delete(pJsonCcb);
}
/*
添加元素到建行卡对象中,组成:
{
"bandname": "CCB",
"bandcard": "123456",
"bandpwd": "543254"
}
*/
cJSON_AddStringToObject(pJsonCcb,"bankname","CCB");
cJSON_AddStringToObject(pJsonCcb,"bankcard","123456");
cJSON_AddStringToObject(pJsonCcb,"bankpwd","543254");
/*
添加元素到农行卡对象中,组成:
{
"bandname": "ABC",
"bandcard": "23456",
"bandpwd": "543254"
}
*/
cJSON_AddStringToObject(pJsonAbc,"bankname","ABC");
cJSON_AddStringToObject(pJsonAbc,"bankcard","23456");
cJSON_AddStringToObject(pJsonAbc,"bankpwd","543254");
/*
两个银行卡添加到数组中,组成:
[
{
"bandname": "CCB",
"bandcard": "123456",
"bandpwd": "543254"
}, {
"bandname": "ABC",
"bandcard": "23456",
"bandpwd": "543254"
}
]
*/
cJSON_AddItemToArray(pJsonBankcard,pJsonCcb);
cJSON_AddItemToArray(pJsonBankcard,pJsonAbc);
/*
添加数学、语文到学科对象,组成:
{
"math": "100",
"Chinese": "98"
}
*/
cJSON_AddStringToObject(pJsonSubject,"math","100");
cJSON_AddStringToObject(pJsonSubject,"Chinese","98");
/*
添加名字、岁数等String类型的元素到根对象
添加学科对象到根对象
添加银行卡数组对象到根对象
最终形成我们的目标json格式。
*/
cJSON_AddStringToObject(pJsonRoot,"name","darren");
cJSON_AddStringToObject(pJsonRoot,"age","25");
cJSON_AddItemToObject(pJsonRoot,"subject",pJsonSubject);
cJSON_AddItemToObject(pJsonRoot,"bankcard",pJsonBankcard);
char* out = cJSON_Print(pJsonRoot);
//printf("Json = %s\n",out);
memcpy(ret,out,strlen(out));
cJSON_Delete(pJsonRoot);
free(out);
return 0;
}
int main()
{
char buffer[2048] = "";
create_json(buffer);
printf("buffer = %s\n",buffer);
return 0;
}
2.3 代码注意事项
1.
cJSON_CreateObject(),cJSON_CreateArray() 函数申请了内存空间,需调用 cJSON_Delete()函数去释放内存。
2.如:
cJSON *pJsonRoot = cJSON_CreateObject();
cJSON *pJsonSubject = cJSON_CreateObject();
cJSON_AddItemToObject(pJsonRoot,"subject",pJsonSubject);
即pJsonRoot包含了pJsonSubject,此时只需要 cJSON_Delete(pJsonRoot);pJsonSubject对象会被随之释放掉。
3.
char* out = cJSON_Print(pJsonRoot);
必须调用free(out)去释放内存。
三.解析json
3.1目标:
1.在事先知道json格式的情况下(一般是约定好的格式),通过name去获取其value
2.解析未知的json,取出所有的name 和value
代码以上述组成的json来去解析。
3.2 代码:
//sign表层级
void print_json(cJSON* data, int sign)
{
if(!data)
return;
int count = sign;
while(count--)
{
printf("\t");
}
//对象类型为cJSON_String,打印name,value
if(data->type == cJSON_String)
{
printf("sign = %d: name = %s, value = %s\n",sign,data->string,data->valuestring);
}
//对象为 cJSON_Array 或 cJSON_Object
else if(data->type == cJSON_Array || data->type == cJSON_Object)
{
//打印name(数组里的元素是无name的)
printf("sign = %d: name = %s\n",sign,data->string);
int i = 0;
//获取对象里元素个数
for(; i < cJSON_GetArraySize(data); i++)
{
cJSON* item = cJSON_GetArrayItem(data,i);
//迭代,并增加层级
print_json(item,sign+1);
}
}
}
void process_json(char* data)
{
//字符串转json对象,使用结束后要delete掉,否则内存泄漏
cJSON* pRoot = cJSON_Parse(data);
if( pRoot == NULL )
{
printf("data is wrong\n");
return;
}
//假定知道json对象格式内容
/*
从pRoot集合,获取名称为"name"的对象,其类型为:cJSON_String
*/
cJSON* pName = cJSON_GetObjectItem(pRoot,"name");
printf("name=%s, value=%s\n",pName->string,pName->valuestring);
/*
从pRoot集合,获取名称为"subject"的对象,其类型为:cJSON_Object
*/
cJSON* pSubject = cJSON_GetObjectItem(pRoot,"subject");
if( pSubject->type == cJSON_Object )
{
/*
从pSubject集合,获取名称为"math"的对象,其类型为:cJSON_String
*/
cJSON* pMath = cJSON_GetObjectItem(pSubject,"math");
printf("name=%s, value=%s\n",pMath->string,pMath->valuestring);
}
/*
从pRoot集合,获取名称为"subject"的对象,其类型为:cJSON_Array
*/
cJSON* pBankcard = cJSON_GetObjectItem(pRoot,"bankcard");
if( pBankcard->type == cJSON_Array )
{
/*
从pBankcard数组,获取它第0个元素,其类型为:cJSON_Object
*/
cJSON* pArray0 = cJSON_GetArrayItem(pBankcard,0);
if( pArray0->type == cJSON_Object )
{
/*
从pBankcard数组第0元素,获取名称为"bankname"的对象,其类型为:cJSON_String
*/
cJSON* pBankName = cJSON_GetObjectItem(pArray0,"bankname");
printf("name=%s, value=%s\n",pBankName->string,pBankName->valuestring);
}
}
//假定未知json数据格式,逐个去获取并打印
print_json(pRoot,0);
//释放内存
cJSON_Delete(pRoot);
}
int main()
{
char buffer[2048] = "";
create_json(buffer);
printf("buffer = %s\n",buffer);
process_json(buffer);
return 0;
}
3.3 代码注意事项
使用 cJSON* pRoot = cJSON_Parse(data),结束后需要 cJSON_Delete(pRoot),否则会内存泄漏