JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,它以易于阅读和编写的文本形式表示结构化数据。JSON 格式广泛用于将数据从一个应用程序传输到另一个应用程序,特别是在Web应用程序中,因为它与JavaScript兼容,容易在客户端和服务器之间进行数据交换。
JSON 数据由两种主要结构构成:
对象 (Object):对象由一对大括号 {}
包围,内部包含一个或多个键值对(key-value pairs)。每个键值对中,键是字符串,值可以是字符串、数字、布尔值、数组、对象或者 null。键和值之间用冒号 :
分隔,键值对之间用逗号 ,
分隔。
例如:
{
"name": "John",
"age": 30,
"isStudent": false
}
数组 (Array):数组由一对方括号 []
包围,内部包含一个或多个值,这些值可以是字符串、数字、布尔值、对象、数组或 null。数组中的值之间用逗号 ,
分隔。
例如:
["apple", "banana", "cherry"]
序列化和反序列化是将数据从一种格式转换为另一种格式的过程:
序列化:序列化是将数据结构(如对象或数组)转换为 JSON 字符串的过程。在编程中,这通常用于将数据转换为可以在网络上传输或存储在文件中的格式。
例如,在JavaScript中,使用 JSON.stringify()
方法可以将一个对象或数组序列化为JSON字符串:
const data = { name: "John", age: 30 };
const jsonString = JSON.stringify(data);
这将生成以下JSON字符串:
{"name":"John","age":30}
反序列化:反序列化是将JSON字符串转换回原始数据结构的过程。这通常用于从网络或文件中读取JSON数据并将其还原为可供程序使用的数据结构。
在JavaScript中,使用 JSON.parse()
方法可以将JSON字符串反序列化为原始对象或数组:
const jsonString = '{"name":"John","age":30}';
const data = JSON.parse(jsonString);
这将把JSON字符串还原为一个包含相同数据的对象。
总之,JSON 是一种常用的数据格式,序列化和反序列化是将数据转换为JSON格式以及将其还原回原始数据结构的重要过程,用于数据交换和持久化存储。
cJSON(C语言JSON)库是一个用于在C语言中解析和生成JSON数据的轻量级开源库。
仓库地址:
https://github.com/DaveGamble/cJSON
它提供了简单而强大的API,使C语言程序能够轻松地处理JSON数据。cJSON库的主要特点包括:
轻量级:cJSON库非常小巧,因此它不会增加太多的内存开销或二进制文件大小,适用于嵌入式系统和资源受限的环境。
易于使用:cJSON提供了一组简单的API函数,使用户能够轻松地解析和生成JSON数据。这些API包括创建JSON对象、数组、字符串、数字等,以及将JSON数据解析成C语言数据结构。
跨平台:cJSON库是跨平台的,可以在多种操作系统和编译器上运行,因此适用于各种C语言项目。
开源:cJSON是开源的,允许用户免费使用和修改它,符合自由软件和开源软件的原则。
支持标准的JSON格式:cJSON库支持标准的JSON格式,可以正确处理JSON对象、数组、字符串、数字、布尔值和null等基本JSON数据类型。
以下是cJSON库的一些基本用法示例:
创建JSON对象和添加键值对:
cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "name", "John");
cJSON_AddNumberToObject(root, "age", 30);
创建JSON数组和添加元素:
cJSON *array = cJSON_CreateArray();
cJSON_AddItemToArray(array, cJSON_CreateString("apple"));
cJSON_AddItemToArray(array, cJSON_CreateString("banana"));
将JSON数据解析成C语言数据结构:
const char *jsonStr = "{\"name\":\"John\",\"age\":30}";
cJSON *root = cJSON_Parse(jsonStr);
const char *name = cJSON_GetObjectItem(root, "name")->valuestring;
int age = cJSON_GetObjectItem(root, "age")->valueint;
生成JSON字符串:
char *jsonStr = cJSON_Print(root);
需要注意的是,使用cJSON库时,应该小心处理内存分配和释放,以避免内存泄漏。cJSON提供了一些用于释放JSON对象的函数,以确保在使用完JSON数据后正确释放相关内存。
cJSON库通常用于C语言项目中需要与JSON数据进行交互的情况,例如与API通信、配置文件解析和生成等。由于其轻量级和易用性,它在许多C语言应用程序中得到了广泛的应用。
下载出来的文件会有很多 但是真正用到的就是只有cJSON.h cJSON.c
appveyor.yml cJSON.c cJSON_Utils.c CMakeLists.txt fuzzing LICENSE README.md tests
CHANGELOG.md cJSON.h cJSON_Utils.h CONTRIBUTORS.md library_config Makefile test.c valgrind.supp
将文件放到项目目录下 包含cJSON.h就可以使用了
cJSON_AddNullToObject(cJSON * const object, const char * const name):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddTrueToObject(cJSON * const object, const char * const name):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddFalseToObject(cJSON * const object, const char * const name):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。boolean
- 要添加的布尔值,非零表示true,零表示false。cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。number
- 要添加的双精度浮点数。cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。string
- 要添加的C字符串。cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。raw
- 要添加的原始JSON字符串。cJSON_AddObjectToObject(cJSON * const object, const char * const name):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddArrayToObject(cJSON * const object, const char * const name):
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。#include
#include"cJSON.h"
int main()
{
cJSON* cjson_test = NULL;
cJSON* cjson_address = NULL;
cJSON* cjson_skill = NULL;
char* str = NULL;
/* 创建一个JSON数据对象(链表头结点) */
cjson_test = cJSON_CreateObject();
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddStringToObject(cjson_test, "name", "SysBent");
/* 添加一条整数类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_test, "age", 22);
/* 添加一条浮点类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(cjson_test, "weight", 55.5);
/* 添加一个嵌套的JSON数据(添加一个链表节点) */
cjson_address = cJSON_CreateObject();
cJSON_AddStringToObject(cjson_address, "country", "China");
cJSON_AddNumberToObject(cjson_address, "zip-code", 500000);
cJSON_AddItemToObject(cjson_test, "address", cjson_address);
/* 添加一个数组类型的JSON数据(添加一个链表节点) */
cjson_skill = cJSON_CreateArray();
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C/C++" ));
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" ));
cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));
cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);
/* 添加一个值为 True 的布尔类型的JSON数据(添加一个链表节点) */
cJSON_AddTrueToObject(cjson_test,"student");
/* 打印JSON对象(整条链表)的所有数据 */
str = cJSON_Print(cjson_test);
printf("JSON String:\n%s\n", str);
return 0;
}
在cJSON库中,反序d列化是指将JSON字符串解析为C语言数据结构的过程。cJSON库提供了一些函数来实现这个过程,其中最常用的函数是 cJSON_Parse()
。以下是关于这个函数的详细解释以及其他相关函数:
cJSON_Parse(const char *value):
value
- 包含JSON数据的C字符串。示例:
const char* json_str = "{\"name\":\"John\",\"age\":30}";
cJSON* parsed_json = cJSON_Parse(json_str);
if (parsed_json != NULL) {
// 解析成功,可以继续操作解析后的JSON数据
// ...
cJSON_Delete(parsed_json); // 释放内存
} else {
// 解析失败,处理错误
// ...
}
cJSON_GetObjectItem(const cJSON *object, const char *string):
object
- 目标JSON对象。string
- 要获取值的键的名称(C字符串)。示例:
const cJSON* name_item = cJSON_GetObjectItem(parsed_json, "name");
if (name_item != NULL) {
const char* name = name_item->valuestring;
printf("Name: %s\n", name);
}
cJSON_GetArrayItem(const cJSON *array, int index):
array
- 目标JSON数组。index
- 要获取的元素的索引(从0开始)。示例:
const cJSON* skill_item = cJSON_GetArrayItem(parsed_json, 0);
if (skill_item != NULL) {
const char* skill = skill_item->valuestring;
printf("Skill 1: %s\n", skill);
}
cJSON_GetArraySize(const cJSON *array):
array
- 目标JSON数组。示例:
int array_size = cJSON_GetArraySize(parsed_json);
printf("Array Size: %d\n", array_size);
这些函数使您能够在解析JSON字符串后,轻松地访问和提取JSON数据的值,以便在C语言程序中使用。要确保在使用完JSON数据后,通过 cJSON_Delete()
函数释放相关内存,以避免内存泄漏。
#include
#include "cJSON.h"
int main() {
const char* json_str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";
cJSON* parsed_json = cJSON_Parse(json_str);
if (parsed_json != NULL) {
// 从JSON对象中获取数据
const char* name = cJSON_GetObjectItem(parsed_json, "name")->valuestring;
int age = cJSON_GetObjectItem(parsed_json, "age")->valueint;
const char* city = cJSON_GetObjectItem(parsed_json, "city")->valuestring;
// 打印获取的数据
printf("Name: %s\n", name);
printf("Age: %d\n", age);
printf("City: %s\n", city);
// 释放内存
cJSON_Delete(parsed_json);
} else {
printf("JSON parsing failed.\n");
}
return 0;
}
在使用cJSON库时,需要特别注意内存管理问题,以避免内存泄漏或内存溢出。以下是在使用cJSON库时可能涉及的一些内存问题和如何处理它们的建议:
内存分配:
cJSON_CreateObject()
、cJSON_CreateArray()
和其他创建函数时分配足够的内存。释放内存:
cJSON_Delete()
函数来释放内存。否则,可能会导致内存泄漏。释放序列化后的字符串内存:
cJSON_Print()
函数将JSON对象序列化为字符串后,需要负责释放字符串内存,以免出现内存泄漏。free()
函数释放这些字符串内存。错误处理:
栈内存和堆内存:
嵌套和循环引用:
内存池:
总之,在使用cJSON库时,良好的内存管理非常重要。要小心处理内存分配、释放和错误处理,以确保您的应用程序在处理JSON数据时不会出现内存问题。同时,根据您的应用需求,考虑使用适当的内存优化策略。
以下是一个示例代码,演示了如何使用cJSON库创建和释放JSON对象以及处理可能涉及的内存问题:
#include
#include "cJSON.h"
int main() {
// 创建一个JSON对象
cJSON* cjson_object = cJSON_CreateObject();
if (cjson_object != NULL) {
// 添加键值对到JSON对象
cJSON_AddStringToObject(cjson_object, "name", "John");
cJSON_AddNumberToObject(cjson_object, "age", 30);
// 序列化JSON对象为字符串
char* json_str = cJSON_Print(cjson_object);
printf("Serialized JSON:\n%s\n", json_str);
// 释放序列化后的字符串内存
free(json_str);
// 释放JSON对象内存
cJSON_Delete(cjson_object);
} else {
printf("Failed to create JSON object.\n");
}
return 0;
}
这个示例中,我们首先创建一个JSON对象 cjson_object
,然后向它添加键值对。接下来,我们使用 cJSON_Print()
函数将JSON对象序列化为字符串,并使用 free()
函数释放序列化后的字符串内存。最后,我们使用 cJSON_Delete()
函数释放JSON对象的内存。
请注意,这个示例仅用于演示内存管理的基本原则。在实际应用中,您可能会处理更复杂的JSON结构,嵌套对象和数组,因此需要更复杂的内存管理策略来确保没有内存泄漏或错误。