JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供差异场景下常见的 JSON 格式示例。
1. 简单对象
JSON 对象是由键值对组成,用花括号 {} 包裹,键和值之间用冒号 : 分隔,多个键值对之间用逗号 , 分隔。
- {
- "name": "John Doe",
- "age": 30,
- "isStudent": false,
- "hometown": null
- }
复制代码 2. 嵌套对象
JSON 对象可以嵌套,即一个对象的键对应的值可以是另一个对象。
- json
- {
- "person": {
- "name": "Alice",
- "age": 25,
- "contact": {
- "email": "alice@example.com",
- "phone": "123-456-7890"
- }
- }
- }
复制代码
3. 数组
JSON 数组是由值组成的有序列表,用方括号 [] 包裹,值之间用逗号 , 分隔。数组中的值可以是差异的数据类型,也可以是对象或数组。
- [
- "apple",
- "banana",
- "cherry"
- ]
复制代码 4. 对象数组
数组中的元素可以是 JSON 对象。
- [
- {
- "id": 1,
- "name": "Product A",
- "price": 19.99
- },
- {
- "id": 2,
- "name": "Product B",
- "price": 29.99
- }
- ]
复制代码
5. 复杂嵌套结构
结合对象和数组可以形成更复杂的嵌套结构。
- {
- "employees": [
- {
- "name": "Bob",
- "department": "Sales",
- "projects": [
- {
- "projectName": "Project X",
- "startDate": "2023-01-01"
- },
- {
- "projectName": "Project Y",
- "startDate": "2023-06-01"
- }
- ]
- },
- {
- "name": "Eve",
- "department": "Marketing",
- "projects": [
- {
- "projectName": "Project Z",
- "startDate": "2023-03-01"
- }
- ]
- }
- ]
- }
复制代码
6. 包罗差异数据类型的对象
- {
- "title": "Sample Document",
- "author": {
- "firstName": "Jane",
- "lastName": "Smith"
- },
- "tags": ["document", "sample"],
- "views": 1234,
- "isPublished": true
- }
复制代码
二、
如果没有现成的 JSON 库,要本身实现 JSON 数据的解析和生成,可以按照 JSON 数据的结构特点,通过字符串处置惩罚来完成。以下分别介绍怎样手动实现 JSON 对象和数组的解析与生成。
1. JSON 解析
解析思绪
JSON 对象:JSON 对象由键值对组成,键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔,团体用花括号 {} 包裹。解析时需要辨认键和值,处置惩罚嵌套对象和数组。
JSON 数组:JSON 数组由值组成,值之间用逗号 , 分隔,团体用方括号 [] 包裹。解析时需要逐个提取数组元素。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- // 跳过空白字符
- void skip_whitespace(const char **json) {
- while (**json == ' ' || **json == '\t' || **json == '\n' || **json == '\r') {
- (*json)++;
- }
- }
- // 解析字符串
- char *parse_string(const char **json) {
- (*json)++; // 跳过起始的双引号
- const char *start = *json;
- while (**json != '\0' && **json != '"') {
- (*json)++;
- }
- size_t len = *json - start;
- char *str = (char *)malloc(len + 1);
- if (str == NULL) {
- return NULL;
- }
- memcpy(str, start, len);
- str[len] = '\0';
- (*json)++; // 跳过结束的双引号
- return str;
- }
- // 解析数字
- int parse_number(const char **json) {
- int num = 0;
- while (**json >= '0' && **json <= '9') {
- num = num * 10 + (**json - '0');
- (*json)++;
- }
- return num;
- }
- // 解析 JSON 对象
- void parse_object(const char **json) {
- (*json)++; // 跳过起始的花括号
- skip_whitespace(json);
- while (**json != '}') {
- char *key = parse_string(json);
- skip_whitespace(json);
- (*json)++; // 跳过冒号
- skip_whitespace(json);
- if (**json == '"') {
- char *value = parse_string(json);
- printf("Key: %s, Value: %s\n", key, value);
- free(value);
- } else if (**json >= '0' && **json <= '9') {
- int value = parse_number(json);
- printf("Key: %s, Value: %d\n", key, value);
- }
- free(key);
- skip_whitespace(json);
- if (**json == ',') {
- (*json)++;
- skip_whitespace(json);
- }
- }
- (*json)++; // 跳过结束的花括号
- }
- // 解析 JSON 数组
- void parse_array(const char **json) {
- (*json)++; // 跳过起始的方括号
- skip_whitespace(json);
- while (**json != ']') {
- if (**json == '"') {
- char *value = parse_string(json);
- printf("Array value: %s\n", value);
- free(value);
- } else if (**json >= '0' && **json <= '9') {
- int value = parse_number(json);
- printf("Array value: %d\n", value);
- }
- skip_whitespace(json);
- if (**json == ',') {
- (*json)++;
- skip_whitespace(json);
- }
- }
- (*json)++; // 跳过结束的方括号
- }
- // 主解析函数
- void parse_json(const char *json) {
- skip_whitespace(&json);
- if (*json == '{') {
- parse_object(&json);
- } else if (*json == '[') {
- parse_array(&json);
- }
- }
- int main() {
- const char *json_str = "{"name": "John", "age": 30}";
- parse_json(json_str);
- return 0;
- }
复制代码

- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- // 生成 JSON 字符串表示的对象
- char *generate_json_object(const char *key, const char *value) {
- size_t key_len = strlen(key);
- size_t value_len = strlen(value);
- size_t json_len = 2 + key_len + 2 + 1 + 2 + value_len + 2; // {} "" : ""
- char *json = (char *)malloc(json_len);
- if (json == NULL) {
- return NULL;
- }
- sprintf(json, "{"%s": "%s"}", key, value);
- return json;
- }
- // 生成 JSON 字符串表示的数组
- char *generate_json_array(const char **values, int count) {
- size_t total_len = 2; // []
- for (int i = 0; i < count; i++) {
- total_len += strlen(values[i]) + 2; // ""
- if (i < count - 1) {
- total_len++; // ,
- }
- }
- char *json = (char *)malloc(total_len);
- if (json == NULL) {
- return NULL;
- }
- json[0] = '[';
- size_t index = 1;
- for (int i = 0; i < count; i++) {
- json[index++] = '"';
- strcpy(json + index, values[i]);
- index += strlen(values[i]);
- json[index++] = '"';
- if (i < count - 1) {
- json[index++] = ',';
- }
- }
- json[index] = ']';
- json[index + 1] = '\0';
- return json;
- }
- int main() {
- const char *key = "name";
- const char *value = "John";
- char *json_obj = generate_json_object(key, value);
- if (json_obj != NULL) {
- printf("JSON object: %s\n", json_obj);
- free(json_obj);
- }
- const char *values[] = {"apple", "banana", "cherry"};
- int count = sizeof(values) / sizeof(values[0]);
- char *json_arr = generate_json_array(values, count);
- if (json_arr != NULL) {
- printf("JSON array: %s\n", json_arr);
- free(json_arr);
- }
- return 0;
- }
复制代码
2
- {
- "employees": [
- {
- "name": "Bob",
- "department": "Sales",
- "projects": [
- {
- "projectName": "Project X",
- "startDate": "2023-01-01"
- },
- {
- "projectName": "Project Y",
- "startDate": "2023-06-01"
- }
- ]
- },
- {
- "name": "Eve",
- "department": "Marketing",
- "projects": [
- {
- "projectName": "Project Z",
- "startDate": "2023-03-01"
- }
- ]
- }
- ]
- }
复制代码 下面是解析该 JSON 数据的 C 语言代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include "cJSON.h"
- int main() {
- const char *json_str = "{"employees": [{"name": "Bob", "department": "Sales", "projects": [{"projectName": "Project X", "startDate": "2023-01-01"}, {"projectName": "Project Y", "startDate": "2023-06-01"}]}, {"name": "Eve", "department": "Marketing", "projects": [{"projectName": "Project Z", "startDate": "2023-03-01"}]}]}";
- // 解析 JSON 字符串
- cJSON *root = cJSON_Parse(json_str);
- if (root == NULL) {
- const char *error_ptr = cJSON_GetErrorPtr();
- if (error_ptr != NULL) {
- fprintf(stderr, "Error before: %s\n", error_ptr);
- }
- return 1;
- }
- // 获取 employees 数组
- cJSON *employees = cJSON_GetObjectItem(root, "employees");
- if (cJSON_IsArray(employees)) {
- int array_size = cJSON_GetArraySize(employees);
- for (int i = 0; i < array_size; i++) {
- cJSON *employee = cJSON_GetArrayItem(employees, i);
- cJSON *name = cJSON_GetObjectItem(employee, "name");
- cJSON *department = cJSON_GetObjectItem(employee, "department");
- if (cJSON_IsString(name) && cJSON_IsString(department)) {
- printf("Employee Name: %s\n", name->valuestring);
- printf("Department: %s\n", department->valuestring);
- }
- // 获取 projects 数组
- cJSON *projects = cJSON_GetObjectItem(employee, "projects");
- if (cJSON_IsArray(projects)) {
- int project_size = cJSON_GetArraySize(projects);
- printf("Projects:\n");
- for (int j = 0; j < project_size; j++) {
- cJSON *project = cJSON_GetArrayItem(projects, j);
- cJSON *projectName = cJSON_GetObjectItem(project, "projectName");
- cJSON *startDate = cJSON_GetObjectItem(project, "startDate");
- if (cJSON_IsString(projectName) && cJSON_IsString(startDate)) {
- printf(" - Project Name: %s\n", projectName->valuestring);
- printf(" Start Date: %s\n", startDate->valuestring);
- }
- }
- }
- printf("\n");
- }
- }
- // 释放 cJSON 对象占用的内存
- cJSON_Delete(root);
- return 0;
- }
复制代码
- 生成 JSON 数据
下面的代码展示了怎样利用 cJSON 库生成一个包罗差异数据类型的 JSON 对象:
- #include <stdio.h>
- #include <stdlib.h>
- #include "cJSON.h"
- int main() {
- // 创建根 JSON 对象
- cJSON *root = cJSON_CreateObject();
- if (root == NULL) {
- fprintf(stderr, "Failed to create JSON object\n");
- return 1;
- }
- // 添加字符串类型的键值对
- cJSON_AddStringToObject(root, "title", "Sample Document");
- // 创建嵌套的 author 对象
- cJSON *author = cJSON_CreateObject();
- if (author == NULL) {
- fprintf(stderr, "Failed to create author object\n");
- cJSON_Delete(root);
- return 1;
- }
- cJSON_AddStringToObject(author, "firstName", "Jane");
- cJSON_AddStringToObject(author, "lastName", "Smith");
- cJSON_AddItemToObject(root, "author", author);
- // 创建 tags 数组
- cJSON *tags = cJSON_CreateArray();
- if (tags == NULL) {
- fprintf(stderr, "Failed to create tags array\n");
- cJSON_Delete(root);
- return 1;
- }
- cJSON_AddItemToArray(tags, cJSON_CreateString("document"));
- cJSON_AddItemToArray(tags, cJSON_CreateString("sample"));
- cJSON_AddItemToObject(root, "tags", tags);
- // 添加数字类型的键值对
- cJSON_AddNumberToObject(root, "views", 1234);
- // 添加布尔类型的键值对
- cJSON_AddBoolToObject(root, "isPublished", 1);
- // 将 JSON 对象转换为字符串
- char *json_str = cJSON_Print(root);
- if (json_str == NULL) {
- fprintf(stderr, "Failed to print JSON object\n");
- cJSON_Delete(root);
- return 1;
- }
- // 打印 JSON 字符串
- printf("%s\n", json_str);
- // 释放内存
- free(json_str);
- cJSON_Delete(root);
- return 0;
- }
复制代码
下面为你展示怎样利用 C 语言结合 cJSON 库,以文件形式读写和保存 JSON 数据。我们会提供两个示例,一个是从文件中读取 JSON 数据并解析,另一个是将生成的 JSON 数据保存到文件中。
1. 从文件读取并解析 JSON 数据
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "cJSON.h"
- // 从文件读取内容到字符串
- char* read_file(const char* filename) {
- FILE* file = fopen(filename, "r");
- if (file == NULL) {
- perror("Failed to open file");
- return NULL;
- }
- // 获取文件大小
- fseek(file, 0, SEEK_END);
- long size = ftell(file);
- fseek(file, 0, SEEK_SET);
- // 分配内存来存储文件内容
- char* buffer = (char*)malloc(size + 1);
- if (buffer == NULL) {
- perror("Failed to allocate memory");
- fclose(file);
- return NULL;
- }
- // 读取文件内容
- fread(buffer, 1, size, file);
- buffer[size] = '\0';
- fclose(file);
- return buffer;
- }
- int main() {
- const char* filename = "input.json";
- char* json_str = read_file(filename);
- if (json_str == NULL) {
- return 1;
- }
- // 解析 JSON 字符串
- cJSON* root = cJSON_Parse(json_str);
- if (root == NULL) {
- const char* error_ptr = cJSON_GetErrorPtr();
- if (error_ptr != NULL) {
- fprintf(stderr, "Error before: %s\n", error_ptr);
- }
- free(json_str);
- return 1;
- }
- // 示例:获取并打印 "name" 字段的值
- cJSON* name = cJSON_GetObjectItem(root, "name");
- if (cJSON_IsString(name)) {
- printf("Name: %s\n", name->valuestring);
- }
- // 释放资源
- free(json_str);
- cJSON_Delete(root);
- return 0;
- }
复制代码 2. 生成 JSON 数据并保存到文件
- #include <stdio.h>
- #include <stdlib.h>
- #include "cJSON.h"
- int main() {
- // 创建根 JSON 对象
- cJSON* root = cJSON_CreateObject();
- if (root == NULL) {
- fprintf(stderr, "Failed to create JSON object\n");
- return 1;
- }
- // 添加键值对
- cJSON_AddStringToObject(root, "name", "John Doe");
- cJSON_AddNumberToObject(root, "age", 30);
- // 将 JSON 对象转换为字符串
- char* json_str = cJSON_Print(root);
- if (json_str == NULL) {
- fprintf(stderr, "Failed to print JSON object\n");
- cJSON_Delete(root);
- return 1;
- }
- // 打开文件以写入模式
- FILE* file = fopen("output.json", "w");
- if (file == NULL) {
- perror("Failed to open file");
- free(json_str);
- cJSON_Delete(root);
- return 1;
- }
- // 将 JSON 字符串写入文件
- fputs(json_str, file);
- // 关闭文件
- fclose(file);
- // 释放内存
- free(json_str);
- cJSON_Delete(root);
- return 0;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |