cJSON库的解析与使用

  • 1、JSON格式简介
  • 1.1、cjson数据结构形式
  • 1.2、cjson语法规则
  • 1.3、cjson的数据类型
  • 2、cJSON核心结构体
  • 3、封装JSON格式
  • 3.1、创建一个对象,并向这个对象里添加字符串和整型键值:
  • 3.2、创建一个数组,并向数组添加一个字符串和一个数字
  • 3.3、 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字
  • 4、解析json得到数据
  • 4.1、解析流程
  • 4.2、解析没有父节点的
  • 4.3、解析object
  • 4.4、解析数组
  • 4.5、解析数组中带对象


1、JSON格式简介


JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。(来自“开源中国”资料)。

cJSON从名字可知,整个项目都是以极标准的C来写的,意思说,可以跨各种平台使用了。 cJSON 是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。

cJSON是一个仅有一个.h文件,一个.c文件组成的JSON解析器,它是由纯C(ANSI C89)实现的,跨平台性较好。使用的时候,自己创建好一个main.c文件后,将头文件include进去。

#include "cJSON.h"


如果是在linux的主机上上,请使用以下命令进行编译(链接libm库):

gcc  *.c  cJSON.c    -lm

1.1、cjson数据结构形式

(1)、对象(object):一个对象以 { 开始,并以 } 结束。一个对象包含一系列非排序的名称/值对,每个名称/值对之间使用”,”分隔。

(2)、名称/值(collection):名称和值之间使用”:”隔开。一个名称是一个字符串;一个值 (value)可以是双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者数组(array)。这些结构可以嵌套。

1.2、cjson语法规则

(1)、数据在键值对中;
(2)、数据由逗号分隔;
(3)、花括号保存对象;
(4)、方括号保存数组。

1.3、cjson的数据类型

/* 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核心结构体中的type的类型

2、cJSON核心结构体

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;

结构体参数说明:

参数

描述

struct cJSON *next,*prev

遍历数组或对象链的前向或后向链表指针

struct cJSON *child

数组或对象的孩子节点

int type

key的类型

char *valuestring

字符串值

int valueint

整数值

double valuedouble

浮点数值

char *string

key的名字

说明:

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的名称。

3、封装JSON格式

一般流程:创建一个对象或数组,在向数组中添加你想要的值

3.1、创建一个对象,并向这个对象里添加字符串和整型键值:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSON.h"


int main(int argc,char ** argv)
{
    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);
    return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行结果:

java cjson Java cjson集成_java cjson

3.2、创建一个数组,并向数组添加一个字符串和一个数字

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSON.h"

void 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); //将json形式打印成正常字符串形式
    if(s)
	{
        printf(" %s \n",s);  //打印输出
        free(s);
    }
    
    if(root)  cJSON_Delete(root);//释放内存
 
}

int main(int argc,char ** argv)
{
	create_js();
	return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行效果:

java cjson Java cjson集成_cjson_02

3.3、 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSON.h"

int create_js(void)
{
    cJSON *root, *js_body, *js_list;
    root = cJSON_CreateObject();  //创建一个object  "{"开头  "}"结尾
    cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray()); //向object中加入body和一个数组"["开头   "]"结尾
    cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject()); //在数组中加入一个object  "{"开头  "}"结尾
    cJSON_AddStringToObject(js_list,"name","fengxin"); //向数组中的object中加入字符串
    cJSON_AddNumberToObject(js_list,"status",100);  //向数组中的object中加入整数
 
    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;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行效果:

java cjson Java cjson集成_java cjson_03


由浅入深,向这些简单的嵌套回了,更复杂的也很简单,只不过多费点力。

4、解析json得到数据

4.1、解析流程

1、首先调用cJSON_Parse()函数,解析JSON数据包,并按照cJSON结构体的结构序列化整个数据包。使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。

cJSON*root=cJSON_Parse(json_string);

(2) 调用cJSON_GetObjectItem()函数,可从cJSON结构体中查找某个子节点名称(键名称),如果查找成功可把该子节点序列化到cJSON结构体中。

cJSON*item=cJSON_GetObjectItem(root,"firstName");

(3) 如果需要使用cJSON结构体中的内容,可通过cJSON结构体中的valueint和valuestring取出有价值的内容(即键的值)

本例子中,我们直接访问 item->valuestring 就获取到 “Brett” 的内容了。

(4) 通过cJSON_Delete(),释放cJSON_Parse()分配出来的内存空间。

cJSON_Delete(root);

4.2、解析没有父节点的

{
	name:fengxin,
	passwd:123,num:1
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"

int main(int argc,char ** argv)
{
	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);  //释放内存 
	
	
	return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行效果:

java cjson Java cjson集成_json_04

4.3、解析object

创建JSON字符串文本文档1.txt:

{
	"list":
	{
		"name":"xiao hong",
		"age":10
	},
	"other":
	{
		"name":"hua hua"
	}
 }

解析:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
 
#include "cJSON.h"


int cJSON_to_str(char *s);

/*获取1.txt中JSON字符串*/
void dofile(char *filename)
{
	FILE *f;
	int len;
	char *data;
	
	f=fopen(filename,"rb");
	fseek(f,0,SEEK_END);
	len=ftell(f);
	fseek(f,0,SEEK_SET);
	data=(char*)malloc(len+1);
	fread(data,1,len,f);
	fclose(f);
	
	printf("read file %s complete, len=%d.\n",filename,len);
 
	printf("data is %s\n",data);
	
	cJSON_to_str(data); /*调用JSON解析*/
	free(data);
}
int cJSON_to_str(char *s)
{
	printf("%s\n",s);
	cJSON *root = cJSON_Parse(s);
	if(!root) {
		printf("get root faild !\n");
		return -1;
	}
	 /*获取list节点类型*/
	cJSON *js_list = cJSON_GetObjectItem(root, "list");
	if(!js_list) {
		printf("no list!\n");
		return -1;
	}
	printf("list type is %d\n",js_list->type);
	 /*获取name类型及其字符串的值*/
	cJSON *name = cJSON_GetObjectItem(js_list, "name");
	if(!name) {
		printf("No name !\n");
		return -1;
	}
	printf("name type is %d\n",name->type);
	printf("name is %s\n",name->valuestring);
	 /*获取age的类型及其值*/
	cJSON *age = cJSON_GetObjectItem(js_list, "age");
	if(!age) {
		printf("no age!\n");
		return -1;
	}
	printf("age type is %d\n", age->type);
	printf("age is %d\n",age->valueint);
	 /*获取other类型*/
	cJSON *js_other = cJSON_GetObjectItem(root, "other");
	if(!js_other) {
		printf("no list!\n");
		return -1;
	}
	printf("list type is %d\n",js_other->type);
	 /*获取name的类型及其值*/
	cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
	if(!js_name) {
		printf("No name !\n");
		return -1;
	}
	printf("name type is %d\n",js_name->type);
	printf("name is %s\n",js_name->valuestring);
	 
	if(root)
		cJSON_Delete(root);  /*释放root*/
		return 0;
}


int main(int argc, char **argv)
{
 
	dofile(argv[1]);
 
	return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行效果:

./aaa  1.txt

java cjson Java cjson集成_cjson_05

4.4、解析数组

创建JSON字符串文本文档1.txt:

{
	"list":
	[
		"name1",
		"name2"
	]
}

解析:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
 
#include "cJSON.h"


int cJSON_to_str(char *s);

void dofile(char *filename)
{
	FILE *f;
	int len;
	char *data;
	
	f=fopen(filename,"rb");
	fseek(f,0,SEEK_END);
	len=ftell(f);
	fseek(f,0,SEEK_SET);
	data=(char*)malloc(len+1);
	fread(data,1,len,f);
	fclose(f);
	
	printf("read file %s complete, len=%d.\n",filename,len);
 
	printf("data is %s\n",data);
	
	cJSON_to_str(data);
	free(data);
}

int cJSON_to_str(char *s)
{
	printf("%s\n",s);
	cJSON *root = cJSON_Parse(s);
	if(!root) {
		printf("get root faild !\n");
		return -1;
	}
	cJSON *js_list = cJSON_GetObjectItem(root, "list");
	if(!js_list){
		printf("no list!\n");
		return -1;
	}
	int array_size = cJSON_GetArraySize(js_list);
	printf("array size is %d\n",array_size);
	int i = 0;
	cJSON *item;
	for(i=0; i< array_size; i++) {
		item = cJSON_GetArrayItem(js_list, i);
		printf("item type is %d\n",item->type);
		printf("%s\n",item->valuestring);
	}
	 
	if(root)
		cJSON_Delete(root);

	return 0;
}

int main(int argc, char **argv)
{
 
	dofile(argv[1]);
 
	return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm
./aaa  1.txt

运行效果:

java cjson Java cjson集成_数组_06

4.5、解析数组中带对象

创建JSON字符串文本文档1.txt:

{
  "list": [
    {
      "name": "xiao hong",
      "age": 10
    },
    {
      "name": "hua hua",
      "age": 11
    }
  ]
}

解析:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
 
#include "cJSON.h"


int cJSON_to_str(char *s);

void dofile(char *filename)
{
	FILE *f;
	int len;
	char *data;
	
	f=fopen(filename,"rb");
	fseek(f,0,SEEK_END);
	len=ftell(f);
	fseek(f,0,SEEK_SET);
	data=(char*)malloc(len+1);
	fread(data,1,len,f);
	fclose(f);
	
	printf("read file %s complete, len=%d.\n",filename,len);
 
	printf("data is %s\n",data);
	
	cJSON_to_str(data);
	free(data);
}

int cJSON_to_str(char *s)
{
	cJSON* root = cJSON_Parse(s);
	if(!root) {
		printf("get root faild !\n");
		return -1;
	}
    cJSON* list = cJSON_GetObjectItem(root, "list");
	if(!list){
		printf("no list!\n");
		return -1;
	}
    printf("list type is %d\n", list->type);
 
    int array_size = cJSON_GetArraySize(list);
    printf("array size is :%d\n", array_size);
    for(int i = 0 ; i < array_size ; i++){
        cJSON *item = cJSON_GetArrayItem(list, i);
        //char *str = cJSON_PrintUnformatted(item);
        cJSON* name = cJSON_GetObjectItem(item, "name");
        printf("name type is %d\n", name->type);
        printf("name:%s\n", name->valuestring);
 
        cJSON* age = cJSON_GetObjectItem(item, "age");
        printf("age type is %d\n", age->type);
        printf("age:%d\n", age->valueint);
    }
	if(root)
		cJSON_Delete(root);
}
int main(int argc, char **argv)
{
 
	dofile(argv[1]);
 
	return 0;
}

编译:

gcc cJSON.c main.c -o aaa -lm

运行效果:

./aaa  1.txt

java cjson Java cjson集成_json_07

好了,到这里大部分都差不多了,更多的嵌套也都大同小异。。