😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 cJSON 使用详细教程🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
本文未经允许,不得转发!!!
JSON的全称是JavaScript Object Notation
(JavaScript 对象标记法),是一种存储和交换数据的语法,是一种轻量级的数据交换格式。JSON 使用 JavaScript 语法,但是 JSON 格式是纯文本的,文本可被任何编程语言作为数据来读取和使用。JSON 格式最初由 Douglas Crockford 提出。
JSON 语法衍生于 JavaScript 对象标记法语法:
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号
{}
容纳对象- 方括号
[]
容纳数组
JSON对象需要使用花括号{}
包含起来。JSON对象的内容就是一条条JSON数据,JSON数据直接用逗号分隔。
JSON 数据写为名称/值
的键值对,其中名称必须使用双引号,名称后面加冒号:
和值就组成一个名称/值
键值对,格式如下:
{ "name":value }
JSON数据需要使用逗号分隔,如下:
{
"name":value,
"name1":value1,
"name2":value2
}
JSON值
JSON数据的值可以使用下面6个类型:
- 字符串:用双引号
""
引起来的字符串;
{"name": "Jack"}
- 数字:可以是整数,也可以是浮点数;
{ "age":18, "weight":56.4 }
- 对象(JSON 对象):用花括号
{}
括起来的一组JSON数据 ;{ "information":{ "school": "编程大学", "grade": 4, "专业": "软件工程" } }
- 数组:用方括号
[]
括起来的一组值;
{"gf_age": [18, 20, 23, 25]}
- 布尔值:true、false
{"isBoy": true}
- null
{"studentPoint": null}
cJSON是一个用C语言编写的JSON数据解析器,它轻便,可移植,是一个简单易用的解析器。它的源码文件只有两个:一个C 文件(cJSON.c)和一个头文件(cJSON.h)。因为它的简单易用,让其GitHub吸引了全球众多的程序员在它的基础上贡献代码。
cJSON的Github地址:https://github.com/DaveGamble/cJSON
拿到源码后,只需要两个源文件:cJSON.c
、cJSON.h
;其他文件编程时不需要。
cJSON支持的类型有下面7种,跟前面说的JSON类型是可以对应上的:
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
cJSON将每个JSON数据(键值对)抽象到一个cJSON的结构体,结构体及注释如下:
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next; // 指向下一条JSON数据
struct cJSON *prev; // 指向上一条JSON数据
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child; // 值为 对象/数组 时,child指向值的对象链表
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string; // JSON 数据的名称
} cJSON;
创作JSON文本的步骤:
cjson_root
;cJSON* cjson_root = cJSON_CreateObject();
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
也可以向使用下面函数创建cJSON对象,再使用cJSON_AddItemToObject
将cJSON对象添加到JSON数据对象/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
还有其他向JSON数据对象添加JSON数据的方法,可以参考cJSON.h
自己摸索。JSON数据对象
的,需要重新创建一个JSON数据对象,再把该对象添加到cjson_root
;cJSON_CreateObject
创建对象;cJSON_AddItemToObject
将对象添加到cjson_root
对象。cjson_root
;cJSON_CreateArray
或下面函数创建数组:/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
调用cJSON_AddItemToArray
将数据添加到数组。if(NULL != cjson_root)
cJSON_Delete(cjson_root);
看例子:
// createJSON.c
#include <stdio.h>
#include "cJSON.h"
int main(void)
{
char* str = NULL;
/* 创建一个JSON数据对象(链表头结点) */
cJSON* cjson_root = cJSON_CreateObject();
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(cjson_root, "name", "Jack");
/* 添加一条整数类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_root, "age", 22);
/* 添加一条浮点类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_root, "weight", 56.4);
/* 创建一个JSON数据对象,并添加到cjson_root */
cJSON* cjson_info = cJSON_CreateObject();
cJSON_AddItemToObject(cjson_info, "school", cJSON_CreateString("编程大学"));
cJSON_AddItemToObject(cjson_info, "grade", cJSON_CreateNumber(4));
cJSON_AddItemToObject(cjson_info, "专业", cJSON_CreateString("软件工程"));
cJSON_AddItemToObject(cjson_root, "information", cjson_info);
/* 添加一个数组类型的JSON数据(添加一个链表节点) */
cJSON* cjson_gfAge = cJSON_CreateArray();
cJSON_AddItemToArray(cjson_gfAge, cJSON_CreateNumber(18));
cJSON_AddItemToArray(cjson_gfAge, cJSON_CreateNumber(20));
cJSON_AddItemToArray(cjson_gfAge, cJSON_CreateNumber(23));
cJSON_AddItemToArray(cjson_gfAge, cJSON_CreateNumber(25));
//cJSON_AddItemToArray(cjson_gfAge, 25); //数组里也要求是JSON数据,所以这样写是错误的
cJSON_AddItemToObject(cjson_root, "gf_age", cjson_gfAge);
/* 添加一个ture类型JSON数据(添加一个链表节点) */
cJSON_AddFalseToObject(cjson_root, "isBoy");
/* 添加一个值为 False 的布尔类型的JSON数据(添加一个链表节点) */
cJSON_AddNullToObject(cjson_root, "studentPoint");
/* 打印JSON对象(整条链表)的所有数据 */
str = cJSON_Print(cjson_root);
printf("%s\n", str);
cJSON_Delete(cjson_root);
return 0;
}
保存代码为createJSON.c,与cJSON.c、cJSON.h 放到同一目录,运行gcc cJSON.c createJSON.c -o createJSON
编译,运行结果如下:
解析JSON文本的步骤:
cJSON_Parse
函数解析JSON数据;cJSON_GetArraySize
获取数组大小,再调用cJSON_GetArrayItem
获取各个数组下标对象;cJSON_IsFalse
、cJSON_IsTrue
可以判断是false还是true;cJSON_IsNull
可以判断是否为null。if(NULL != cjson_root)
cJSON_Delete(cjson_root);
看例子:
// parseJSON.c
#include <stdio.h>
#include "cJSON.h"
int main()
{
char *jsonBuf =
"{\
\"name\": \"Jack\", \
\"age\": 22, \
\"weight\": 56.4, \
\"information\": { \
\"school\": \"编程大学\", \
\"grade\": 4, \
\"专业\": \"软件工程\" \
}, \
\"gf_age\": [18, 20, 23, 25], \
\"isBoy\": false, \
\"studentPoint\": null \
}";
//printf("[%s]\n", jsonBuf);
// 解析JSON数据
cJSON* cjson_root = cJSON_Parse(jsonBuf);
if(cjson_root == NULL)
{
printf("parse fail.\n");
return -1;
}
// 根据名称依次获取各个JSON数据对象
cJSON* cjson_name = cJSON_GetObjectItem(cjson_root, "name");
cJSON* cjson_age = cJSON_GetObjectItem(cjson_root, "age");
cJSON* cjson_weight = cJSON_GetObjectItem(cjson_root, "weight");
printf("name=%s, age=%d weight=%f\n",
cJSON_GetStringValue(cjson_name), cjson_age->valueint, cJSON_GetNumberValue(cjson_weight));
// JSON数据值是对象的解析
cJSON* cjson_info = cJSON_GetObjectItem(cjson_root, "information");
cJSON* cjson_info_school = cJSON_GetObjectItem(cjson_info, "school");
cJSON* cjson_info_grade = cJSON_GetObjectItem(cjson_info, "grade");
cJSON* cjson_info_speciality = cJSON_GetObjectItem(cjson_info, "专业");
printf("school=%s grade=%d 专业=%s\n",
cjson_info_school->valuestring, cjson_info_grade->valueint, cjson_info_speciality->valuestring);
// JSON数据值是数组的解析
cJSON* cjson_gf_age = cJSON_GetObjectItem(cjson_root, "gf_age");
int arrSize=cJSON_GetArraySize(cjson_gf_age);
int i=0;
for(i=0; i<arrSize; i++)
{
cJSON* cjson_index = cJSON_GetArrayItem(cjson_gf_age, i);
printf("array_%d=%d, ",i,cjson_index->valueint);
}
printf("\n");
// JSON数据值是布尔值的解析
cJSON* cjson_isBoy = cJSON_GetObjectItem(cjson_root, "isBoy");
if(cJSON_IsFalse(cjson_isBoy))
{
printf("isBoy:false\n");
}
else if(cJSON_IsTrue(cjson_isBoy))
{
printf("isBoy:true\n");
}
// JSON数据值是null的解析
cJSON* cjson_studentPoint = cJSON_GetObjectItem(cjson_root, "studentPoint");
if(cJSON_IsNull(cjson_studentPoint))
{
printf("studentPoint:null\n");
}
cJSON_Delete(cjson_root);
return 0;
}
保存代码为parseJSON.c,与cJSON.c、cJSON.h 放到同一目录,运行gcc cJSON.c parseJSON.c -o parseJSON
编译,运行结果如下:
👉本文介绍了JSON数据,cJSON开源库,以及详细介绍cJSON创作JSON文本的步骤,cJOSN解析JSON文本的步骤。
思考一个问题:解析过程中,是否需要释放每一个使用的cJSON*
变量,还是只需要释放cjson_root
就够了?
我的想法是只释放cjson_root
,因为所有其他JSON数据也附着在cjson_root
上的。
如果文章有帮助的话,点赞👍、收藏?,支持一波,谢谢 😁😁😁