“JSON”的全称是“JavaScriptObject Notation”,即JavaScript对象符号,是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。JSON采用与编程语言无关的文本格式,但是也使用了类C语言(包括C、C++、C#、Java、JavaScript、Python等)的习惯,这些特性使JSON成为理想的数据交换格式。
JSON建构于两种结构
(1)“名称/值”对的集合。不同的语言中,其被理解为对象(“object”)、纪录(“record”)、结构(“struct”)、字典(“dictionary”)、哈希表(“hash table”)、有键列表(“keyed list”)或者关联数组(“associativearray”)。
(2)值的有序列表。在大部分语言中,其被理解为数组(“array”)。
简单理解,JSON的定义由以下四句话就全部定义了。
- 并列的数据之间用逗号(”,”)分隔。
- 映射用冒号(”:”)表示。
- 并列数据的集合(数组)用方括号("[]")表示。
- 映射的集合(对象)用大括号(”{}”)表示。
cJSON数据结构定义
/* The cJSON structure: */ typedef struct cJSON { struct cJSON *next,*prev; /* 如果该Json结构在数组中,则它的前后节点*/ struct cJSON *child; /* 如果存在子对象,其第一个子对象*/ int type; /* 键的类型Json对象的类型,可以是字符串,整型或者浮点型*/ char *valuestring; /* 字符串The item's string, if type==cJSON_String*/ int valueint; /* 整型The item's number, if type==cJSON_Number*/ double valuedouble; /* 浮点型The item's number, if type==cJSON_Number*/ char *string; /* “键”的名称Json对象的名字*/ } cJSON; |
Json对象的类型
/* cJSON Types: */ #define cJSON_False 0 #define cJSON_True 1 #define cJSON_NULL 2 #define cJSON_Number 3 #define cJSON_String 4 #define cJSON_Array 5 #define cJSON_Object 6 |
cJson中的基本函数API
函数功能 | 解析函数 |
函数定义 | extern cJSON *cJSON_Parse(const char *value) |
函数说明 | 传入一个字符串,并按照cJSON结构体的结构序列化整个数据包,可以通过if (!json)来判断解析是否出错,如果出错,可以通过printf("Error before: [%s]\n",cJSON_GetErrorPtr())打印出错位置。使用该函数会通过malloc函数在内存中开辟一个空间,使用完成需要手动释放,调用cJSON_Delete()。 |
函数功能 | 打印cJSON |
函数定义 | extern char *cJSON_Print(cJSON *item) |
函数说明 | 传入一个cJSON,将会以排好版的格式打印JSON。完成后需要释放分配的内存空间,调用free()。 |
函数功能 | 释放cJSON内存空间 |
函数定义 | extern void cJSON_Delete(cJSON *c) |
函数说明 | 获得了一个cJSON,当使用完了之后要删除,因为返回的cJSON是通过malloc的方式分配的,如果用完不及时释放会造成内存泄露。 |
函数功能 | 获取cJSON大小 |
函数定义 | extern int cJSON_GetArraySize(cJSON *array) |
函数说明 | 返回数组或对象中的大小,只要该对象下包括其他对象,各对象一般以“,”分隔。 |
函数功能 | 以index的方式获取cJSON数组或对象相应的项 |
函数定义 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item) |
函数说明 | 返回数组或对象中相应index的项,找不到会返回NULL。 |
函数功能 | 以名称的方式获取cJSON数组或对象相应的项 |
函数定义 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) |
函数说明 | 获取当前cJSON对象下有名字的cJSON对象,找不到会返回NULL。 |
函数功能 | 创建cJSON对象 |
函数定义 | extern cJSON *cJSON_CreateObject(void) |
函数说明 | 创建cJSON对象项,从内存中分配空间,内存不够返回NULL。然后通过cJSON_AddItemToObject将分配的空间增加到其他空间上,所以不需要重复删除内存空间。 |
函数功能 | 添加一个对象项到一个指定的对象上 |
函数定义 | extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) |
函数说明 | 一般创建子对象是需要用到,将子对象添加到父对象上。 |
例说
以JSON中国网站的例子,测试代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
char *makeJson()
{
cJSON * pJsonRoot = cJSON_CreateObject();
if(NULL == pJsonRoot)
{
// create object faild, exit
return NULL;
}
cJSON_AddStringToObject(pJsonRoot, "name", "JSON中国");
cJSON_AddStringToObject(pJsonRoot, "url", "http://www.json.org.cn");
cJSON_AddNumberToObject(pJsonRoot, "page", 88);
cJSON_AddBoolToObject(pJsonRoot, "isNonProfit", 1);
cJSON * pJsonSub = cJSON_CreateObject();
if(NULL == pJsonSub)
{
// create object faild, exit
cJSON_Delete(pJsonRoot);
return NULL;
}
cJSON_AddItemToObject(pJsonRoot, "address", pJsonSub);
cJSON_AddStringToObject(pJsonSub, "street", "浙大路38号.");
cJSON_AddStringToObject(pJsonSub, "city", "浙江杭州");
cJSON_AddStringToObject(pJsonSub, "country", "中国");
pJsonSub = cJSON_CreateArray();
if(NULL == pJsonSub)
{
// create object faild, exit
cJSON_Delete(pJsonRoot);
return NULL;
}
cJSON_AddItemToObject(pJsonRoot, "links", pJsonSub);
cJSON * pJsonSubSub;
pJsonSubSub = cJSON_CreateObject();
if(NULL == pJsonSubSub)
{
// create object faild, exit
cJSON_Delete(pJsonRoot);
return NULL;
}
cJSON_AddItemToArray(pJsonSub, pJsonSubSub);
cJSON_AddStringToObject(pJsonSubSub, "name", "Google");
cJSON_AddStringToObject(pJsonSubSub, "url", "http://www.google.com");
pJsonSubSub = cJSON_CreateObject();
if(NULL == pJsonSubSub)
{
// create object faild, exit
cJSON_Delete(pJsonRoot);
return NULL;
}
cJSON_AddItemToArray(pJsonSub, pJsonSubSub);
cJSON_AddStringToObject(pJsonSubSub, "name", "Baidu");
cJSON_AddStringToObject(pJsonSubSub, "url", "http://www.baidu.com");
pJsonSubSub = cJSON_CreateObject();
if(NULL == pJsonSubSub)
{
// create object faild, exit
cJSON_Delete(pJsonRoot);
return NULL;
}
cJSON_AddItemToArray(pJsonSub, pJsonSubSub);
cJSON_AddStringToObject(pJsonSubSub, "name", "SoSo");
cJSON_AddStringToObject(pJsonSubSub, "url", "http://www.SoSo.com");
//char * p = cJSON_Print(pJsonRoot);
char * p = cJSON_PrintUnformatted(pJsonRoot); //free(p);
if(NULL == p)
{
cJSON_Delete(pJsonRoot);
return NULL;
}
//convert json list to string faild, exit
//because sub json pJsonSubSub han been add to pJsonRoot, so just delete pJsonRoot,
//if you also delete pJsonSubSub, it will coredump, and error is : double free
cJSON_Delete(pJsonRoot);
return p;
}
char *parseJson(char *pMsg)
{
int i;
if(NULL == pMsg)
{
return NULL;
}
cJSON *pJsonRoot = cJSON_Parse(pMsg);
if(NULL == pJsonRoot)
{
// parse faild, return
return NULL;
}
// get string from json
cJSON * pJsonSub = cJSON_GetObjectItem(pJsonRoot, "name");
if(NULL == pJsonSub)
{
//get object named "name" faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("name : %s\n", pJsonSub->valuestring);
cJSON_ReplaceItemInObject(pJsonRoot,"name",cJSON_CreateString("JSON中国 1"));//修改json的数据
// get string from json
pJsonSub = cJSON_GetObjectItem(pJsonRoot, "url");
if(NULL == pJsonSub)
{
//get object named "url" faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("url : %s\n", pJsonSub->valuestring);
cJSON_ReplaceItemInObject(pJsonRoot,"url",cJSON_CreateString("http://www.json.org.cn 1"));//修改json的数据
// get number from json
pJsonSub = cJSON_GetObjectItem(pJsonRoot, "page");
if(NULL == pJsonSub)
{
//get number from "page" faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("page : %d\n", pJsonSub->valueint);
cJSON_ReplaceItemInObject(pJsonRoot,"page",cJSON_CreateNumber(88+1));//修改json的数据
// get bool from json
pJsonSub = cJSON_GetObjectItem(pJsonRoot, "isNonProfit");
if(NULL == pJsonSub)
{
// get bool from "isNonProfit" faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("isNonProfit : %d\n", pJsonSub->valueint);
cJSON_ReplaceItemInObject(pJsonRoot,"isNonProfit",cJSON_CreateBool(0));//修改json的数据
// get sub object
pJsonSub = cJSON_GetObjectItem(pJsonRoot, "address");
if(NULL == pJsonSub)
{
// get sub object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
// get sub sub object
cJSON *pJsonSubSub = cJSON_GetObjectItem(pJsonSub, "street");
if(NULL == pJsonSubSub)
{
// get object from subject object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("address->street : %s\n", pJsonSubSub->valuestring);
cJSON_ReplaceItemInObject(pJsonSub,"street",cJSON_CreateString("浙大路38号. 1"));//修改json的数据
pJsonSubSub = cJSON_GetObjectItem(pJsonSub, "city");
if(NULL == pJsonSubSub)
{
// get object from subject object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("address->city : %s\n", pJsonSubSub->valuestring);
cJSON_ReplaceItemInObject(pJsonSub,"city",cJSON_CreateString("浙江杭州 1"));//修改json的数据
pJsonSubSub = cJSON_GetObjectItem(pJsonSub, "country");
if(NULL == pJsonSubSub)
{
// get object from subject object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("address->country : %s\n", pJsonSubSub->valuestring);
cJSON_ReplaceItemInObject(pJsonSub,"country",cJSON_CreateString("中国 1"));//修改json的数据
pJsonSub = cJSON_GetObjectItem(pJsonRoot, "links");
if(NULL == pJsonSub)
{
// get sub object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
for (i = 0; i < cJSON_GetArraySize(pJsonSub); i++)
{
cJSON *pJsonSubArry = cJSON_GetArrayItem(pJsonSub, i);
if(NULL == pJsonSubArry)
{
// get sub object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
pJsonSubSub = cJSON_GetObjectItem(pJsonSubArry, "name");
if(NULL == pJsonSub)
{
// get object from subject object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("links[%d]->name : %s\n", i, pJsonSubSub->valuestring);
cJSON_ReplaceItemInObject(pJsonSubArry,"name",cJSON_CreateString("name 1"));//修改json的数据
pJsonSubSub = cJSON_GetObjectItem(pJsonSubArry, "url");
if(NULL == pJsonSubSub)
{
// get object from subject object faild
cJSON_Delete(pJsonRoot);
return NULL;
}
printf("links[%d]->url : %s\n", i, pJsonSubSub->valuestring);
cJSON_ReplaceItemInObject(pJsonSubArry,"url",cJSON_CreateString("url 1"));//修改json的数据
}
char * p = cJSON_Print(pJsonRoot);
//char * p = cJSON_PrintUnformatted(pJsonRoot); //free(p);
if(NULL == p)
{
cJSON_Delete(pJsonRoot);
return NULL;
}
//Call cJSON_Delete when finished.
cJSON_Delete(pJsonRoot);
return p;
}
int main()
{
FILE *fp = fopen("test.txt", "w");
if (fp == NULL)
exit(1);
printf("===============================\r\n\r\n");
printf("===============================\r\n\r\n");
char * p = makeJson();
if(NULL == p)
{
exit(1);
}
printf("%s\n", p);
printf("===============================\r\n\r\n");
printf("===============================\r\n\r\n");
p = parseJson(p);
printf("===============================\r\n\r\n");
printf("===============================\r\n\r\n");
printf("%s\n", p);
fputs(p, fp);
free(p);//千万不要忘记释放内存呀,cJSON_Print()函数或者cJSON_PrintUnformatted()产生的内存,使用free(char *)进行释放
fclose(fp);
return 0;
}