JSON
(JavaScript Object Notation,JavaScript对象表示法)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。
JSON 数据格式与语言无关,脱胎自JavaScript,但当前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。
JSON 解析器和 JSON 库支持许多不同的编程语言。 JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。 由于这种相似性, 无需解析器, JavaScript 程序能够使用内建的 eval() 函数, 用 JSON 数据来生成原生的 JavaScript 对象。
JSON 是存储和交换文本信息的语法。 类似 XML。 JSON 比 XML 更小、 更快, 更易解析。
JSON 具有自我描述性, 语法简洁, 易于理解。
JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
JSON的三种语法:
键/值对 key:value,用半角冒号分割。 比如 “name”:“Faye” 文档对象 JSON对象写在花括号中,可以包含多个键/值对。比如{ “name”:“Faye” ,“address”:“北京” }。 数组 JSON 数组在方括号中书写: 数组成员可以是对象,值,也可以是数组(只要有意义)。{“love”: [“乒乓球”,“高尔夫”,“斯诺克”,“羽毛球”,“LOL”,“撩妹”]}
cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有不到一千行,代码的可读性也很好,很适合作为C语言项目进行学习。
项目主页
项目github主页
cJSON源码解析、下载与安装:
git clone https://github.com/DaveGamble/cJSON
#下载完成后,切换至下载目录
mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=Off -DENABLE_CJSON_TEST=On -DCMAKE_INSTALL_PREFIX=/usr (生成bin+lib)
cmake .. -DENABLE_CJSON_UTILS=Off -DENABLE_CJSON_TEST=On -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=Off (生成bin)
make
sudo make install (安装libcjson.so)
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
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; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} 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的名称。
重要的接口函数:
1.cJSON *cJSON_Parse(const char *value);
解析JSON数据包,并按照cJSON结构体的结构序列化整个数据包。可以看做是获取一个句柄。
2.cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
功能:获取json指定的对象成员
参数:*objec:第一个函数中获取的句柄。
string:需要获取的对象
返回值:这个对象成员的句柄 如果json格式的对象成员直接就是字符串那么就可以直接通过结构体中的valuestring元素来获取这个成员的值
3.cJSON *cJSON_GetArrayItem(cJSON *array,int item);
功能:有可能第二个函数中获取到的是成员对象值是一个数组,那么就需要用到这个函数。用来获取这个数组指定的下标对象
参数:*array:传入第二步中返回的值
item:想要获取这个数组的下标元素
返回值:这个数组中指定下标的对象。然后在对这个返回值重复使用第二步函数就可以获取到各个成员的值了。
也就是说对象是数组的比是字符串的要多用一个cJSON_GetArrayItem函数,其他的没区别。
4.cJSON_Delete()
用来释放你第一步获取的句柄,来释放整个内存。用在解析完后调用
介绍完了下面就看实例
用于解析的json结构,这里我使用配置文件保存的json结构,然后解析这个配置文件。用于测试json结构如下:
{“syslog_db”:[{“db_user”:“xxx”,“db_password”:“yyy”,“db_type”:“ORACLE”,“db_ip”:“172.16.1.248”,“db_port”:“1521”,“db_name”:“orcl”,“sql”:“select * from syslog”}],
“syslog_source”:[{“send_ip”:“172.0.0.8”,“send_port”:“8”,“send_protocal”:“TCP”}],
“syslog_enable”:“1”
}
#include <stdio.h>
#include "cJSON.h"
int main() {
FILE *fp = NULL;
cJSON *json;
char *out;
char line[1024] = {0};
if(NULL != (fp = fopen("./test.ply", "r"))) {
while (NULL != fgets(line, sizeof(line), fp)) {
json=cJSON_Parse(line); //获取整个大的句柄
out=cJSON_Print(json); //这个是可以输出的。为获取的整个json的值
cJSON *arrayItem = cJSON_GetObjectItem(json,"syslog_db"); //获取这个对象成员
cJSON *object = cJSON_GetArrayItem(arrayItem,0); //因为这个对象是个数组获取,且只有一个元素所以写下标为0获取
/*下面就是可以重复使用cJSON_GetObjectItem来获取每个成员的值了*/
cJSON *item = cJSON_GetObjectItem(object,"db_user"); //
printf("db_user:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"db_password");
printf("db_password:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"db_type");
printf("db_type:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"db_ip");
printf("db_ip:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"db_port");
printf("db_port:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"db_name");
printf("db_name:%s\n",item->valuestring);
item = cJSON_GetObjectItem(object,"sql");
printf("db_sql:%s\n",item->valuestring);
/*这里这个是直接可以获取值的*/
arrayItem = cJSON_GetObjectItem(json,"syslog_enable");
printf("%s\n",arrayItem->valuestring);
}
}
cJSON_Delete(json);
close(fp);
}