JSON格式,C语言本身实现,以及直接调用库函数(一) ...

打印 上一主题 下一主题

主题 877|帖子 877|积分 2631

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。以下为你提供差异场景下常见的 JSON 格式示例。
1. 简单对象
JSON 对象是由键值对组成,用花括号 {} 包裹,键和值之间用冒号 : 分隔,多个键值对之间用逗号 , 分隔。
  1. {
  2.     "name": "John Doe",
  3.     "age": 30,
  4.     "isStudent": false,
  5.     "hometown": null
  6. }
复制代码
2. 嵌套对象
JSON 对象可以嵌套,即一个对象的键对应的值可以是另一个对象。
  1. json
  2. {
  3.     "person": {
  4.         "name": "Alice",
  5.         "age": 25,
  6.         "contact": {
  7.             "email": "alice@example.com",
  8.             "phone": "123-456-7890"
  9.         }
  10.     }
  11. }
复制代码

3. 数组
JSON 数组是由值组成的有序列表,用方括号 [] 包裹,值之间用逗号 , 分隔。数组中的值可以是差异的数据类型,也可以是对象或数组。
  1. [
  2.     "apple",
  3.     "banana",
  4.     "cherry"
  5. ]
复制代码
4. 对象数组
数组中的元素可以是 JSON 对象。
  1. [
  2.     {
  3.         "id": 1,
  4.         "name": "Product A",
  5.         "price": 19.99
  6.     },
  7.     {
  8.         "id": 2,
  9.         "name": "Product B",
  10.         "price": 29.99
  11.     }
  12. ]
复制代码

5. 复杂嵌套结构
结合对象和数组可以形成更复杂的嵌套结构。
  1. {
  2.     "employees": [
  3.         {
  4.             "name": "Bob",
  5.             "department": "Sales",
  6.             "projects": [
  7.                 {
  8.                     "projectName": "Project X",
  9.                     "startDate": "2023-01-01"
  10.                 },
  11.                 {
  12.                     "projectName": "Project Y",
  13.                     "startDate": "2023-06-01"
  14.                 }
  15.             ]
  16.         },
  17.         {
  18.             "name": "Eve",
  19.             "department": "Marketing",
  20.             "projects": [
  21.                 {
  22.                     "projectName": "Project Z",
  23.                     "startDate": "2023-03-01"
  24.                 }
  25.             ]
  26.         }
  27.     ]
  28. }
复制代码

6. 包罗差异数据类型的对象
  1. {
  2.     "title": "Sample Document",
  3.     "author": {
  4.         "firstName": "Jane",
  5.         "lastName": "Smith"
  6.     },
  7.     "tags": ["document", "sample"],
  8.     "views": 1234,
  9.     "isPublished": true
  10. }
复制代码

二、
如果没有现成的 JSON 库,要本身实现 JSON 数据的解析和生成,可以按照 JSON 数据的结构特点,通过字符串处置惩罚来完成。以下分别介绍怎样手动实现 JSON 对象和数组的解析与生成。
1. JSON 解析
解析思绪
JSON 对象:JSON 对象由键值对组成,键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔,团体用花括号 {} 包裹。解析时需要辨认键和值,处置惩罚嵌套对象和数组。
JSON 数组:JSON 数组由值组成,值之间用逗号 , 分隔,团体用方括号 [] 包裹。解析时需要逐个提取数组元素。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. // 跳过空白字符
  5. void skip_whitespace(const char **json) {
  6.     while (**json == ' ' || **json == '\t' || **json == '\n' || **json == '\r') {
  7.         (*json)++;
  8.     }
  9. }
  10. // 解析字符串
  11. char *parse_string(const char **json) {
  12.     (*json)++;  // 跳过起始的双引号
  13.     const char *start = *json;
  14.     while (**json != '\0' && **json != '"') {
  15.         (*json)++;
  16.     }
  17.     size_t len = *json - start;
  18.     char *str = (char *)malloc(len + 1);
  19.     if (str == NULL) {
  20.         return NULL;
  21.     }
  22.     memcpy(str, start, len);
  23.     str[len] = '\0';
  24.     (*json)++;  // 跳过结束的双引号
  25.     return str;
  26. }
  27. // 解析数字
  28. int parse_number(const char **json) {
  29.     int num = 0;
  30.     while (**json >= '0' && **json <= '9') {
  31.         num = num * 10 + (**json - '0');
  32.         (*json)++;
  33.     }
  34.     return num;
  35. }
  36. // 解析 JSON 对象
  37. void parse_object(const char **json) {
  38.     (*json)++;  // 跳过起始的花括号
  39.     skip_whitespace(json);
  40.     while (**json != '}') {
  41.         char *key = parse_string(json);
  42.         skip_whitespace(json);
  43.         (*json)++;  // 跳过冒号
  44.         skip_whitespace(json);
  45.         if (**json == '"') {
  46.             char *value = parse_string(json);
  47.             printf("Key: %s, Value: %s\n", key, value);
  48.             free(value);
  49.         } else if (**json >= '0' && **json <= '9') {
  50.             int value = parse_number(json);
  51.             printf("Key: %s, Value: %d\n", key, value);
  52.         }
  53.         free(key);
  54.         skip_whitespace(json);
  55.         if (**json == ',') {
  56.             (*json)++;
  57.             skip_whitespace(json);
  58.         }
  59.     }
  60.     (*json)++;  // 跳过结束的花括号
  61. }
  62. // 解析 JSON 数组
  63. void parse_array(const char **json) {
  64.     (*json)++;  // 跳过起始的方括号
  65.     skip_whitespace(json);
  66.     while (**json != ']') {
  67.         if (**json == '"') {
  68.             char *value = parse_string(json);
  69.             printf("Array value: %s\n", value);
  70.             free(value);
  71.         } else if (**json >= '0' && **json <= '9') {
  72.             int value = parse_number(json);
  73.             printf("Array value: %d\n", value);
  74.         }
  75.         skip_whitespace(json);
  76.         if (**json == ',') {
  77.             (*json)++;
  78.             skip_whitespace(json);
  79.         }
  80.     }
  81.     (*json)++;  // 跳过结束的方括号
  82. }
  83. // 主解析函数
  84. void parse_json(const char *json) {
  85.     skip_whitespace(&json);
  86.     if (*json == '{') {
  87.         parse_object(&json);
  88.     } else if (*json == '[') {
  89.         parse_array(&json);
  90.     }
  91. }
  92. int main() {
  93.     const char *json_str = "{"name": "John", "age": 30}";
  94.     parse_json(json_str);
  95.     return 0;
  96. }
复制代码


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. // 生成 JSON 字符串表示的对象
  5. char *generate_json_object(const char *key, const char *value) {
  6.     size_t key_len = strlen(key);
  7.     size_t value_len = strlen(value);
  8.     size_t json_len = 2 + key_len + 2 + 1 + 2 + value_len + 2;  // {} "" : ""
  9.     char *json = (char *)malloc(json_len);
  10.     if (json == NULL) {
  11.         return NULL;
  12.     }
  13.     sprintf(json, "{"%s": "%s"}", key, value);
  14.     return json;
  15. }
  16. // 生成 JSON 字符串表示的数组
  17. char *generate_json_array(const char **values, int count) {
  18.     size_t total_len = 2;  // []
  19.     for (int i = 0; i < count; i++) {
  20.         total_len += strlen(values[i]) + 2;  // ""
  21.         if (i < count - 1) {
  22.             total_len++;  // ,
  23.         }
  24.     }
  25.     char *json = (char *)malloc(total_len);
  26.     if (json == NULL) {
  27.         return NULL;
  28.     }
  29.     json[0] = '[';
  30.     size_t index = 1;
  31.     for (int i = 0; i < count; i++) {
  32.         json[index++] = '"';
  33.         strcpy(json + index, values[i]);
  34.         index += strlen(values[i]);
  35.         json[index++] = '"';
  36.         if (i < count - 1) {
  37.             json[index++] = ',';
  38.         }
  39.     }
  40.     json[index] = ']';
  41.     json[index + 1] = '\0';
  42.     return json;
  43. }
  44. int main() {
  45.     const char *key = "name";
  46.     const char *value = "John";
  47.     char *json_obj = generate_json_object(key, value);
  48.     if (json_obj != NULL) {
  49.         printf("JSON object: %s\n", json_obj);
  50.         free(json_obj);
  51.     }
  52.     const char *values[] = {"apple", "banana", "cherry"};
  53.     int count = sizeof(values) / sizeof(values[0]);
  54.     char *json_arr = generate_json_array(values, count);
  55.     if (json_arr != NULL) {
  56.         printf("JSON array: %s\n", json_arr);
  57.         free(json_arr);
  58.     }
  59.     return 0;
  60. }
复制代码

2

  1. {
  2.     "employees": [
  3.         {
  4.             "name": "Bob",
  5.             "department": "Sales",
  6.             "projects": [
  7.                 {
  8.                     "projectName": "Project X",
  9.                     "startDate": "2023-01-01"
  10.                 },
  11.                 {
  12.                     "projectName": "Project Y",
  13.                     "startDate": "2023-06-01"
  14.                 }
  15.             ]
  16.         },
  17.         {
  18.             "name": "Eve",
  19.             "department": "Marketing",
  20.             "projects": [
  21.                 {
  22.                     "projectName": "Project Z",
  23.                     "startDate": "2023-03-01"
  24.                 }
  25.             ]
  26.         }
  27.     ]
  28. }
复制代码
下面是解析该 JSON 数据的 C 语言代码:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "cJSON.h"
  4. int main() {
  5.     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"}]}]}";
  6.     // 解析 JSON 字符串
  7.     cJSON *root = cJSON_Parse(json_str);
  8.     if (root == NULL) {
  9.         const char *error_ptr = cJSON_GetErrorPtr();
  10.         if (error_ptr != NULL) {
  11.             fprintf(stderr, "Error before: %s\n", error_ptr);
  12.         }
  13.         return 1;
  14.     }
  15.     // 获取 employees 数组
  16.     cJSON *employees = cJSON_GetObjectItem(root, "employees");
  17.     if (cJSON_IsArray(employees)) {
  18.         int array_size = cJSON_GetArraySize(employees);
  19.         for (int i = 0; i < array_size; i++) {
  20.             cJSON *employee = cJSON_GetArrayItem(employees, i);
  21.             cJSON *name = cJSON_GetObjectItem(employee, "name");
  22.             cJSON *department = cJSON_GetObjectItem(employee, "department");
  23.             if (cJSON_IsString(name) && cJSON_IsString(department)) {
  24.                 printf("Employee Name: %s\n", name->valuestring);
  25.                 printf("Department: %s\n", department->valuestring);
  26.             }
  27.             // 获取 projects 数组
  28.             cJSON *projects = cJSON_GetObjectItem(employee, "projects");
  29.             if (cJSON_IsArray(projects)) {
  30.                 int project_size = cJSON_GetArraySize(projects);
  31.                 printf("Projects:\n");
  32.                 for (int j = 0; j < project_size; j++) {
  33.                     cJSON *project = cJSON_GetArrayItem(projects, j);
  34.                     cJSON *projectName = cJSON_GetObjectItem(project, "projectName");
  35.                     cJSON *startDate = cJSON_GetObjectItem(project, "startDate");
  36.                     if (cJSON_IsString(projectName) && cJSON_IsString(startDate)) {
  37.                         printf("  - Project Name: %s\n", projectName->valuestring);
  38.                         printf("    Start Date: %s\n", startDate->valuestring);
  39.                     }
  40.                 }
  41.             }
  42.             printf("\n");
  43.         }
  44.     }
  45.     // 释放 cJSON 对象占用的内存
  46.     cJSON_Delete(root);
  47.     return 0;
  48. }
复制代码

  • 生成 JSON 数据
    下面的代码展示了怎样利用 cJSON 库生成一个包罗差异数据类型的 JSON 对象:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "cJSON.h"
  4. int main() {
  5.     // 创建根 JSON 对象
  6.     cJSON *root = cJSON_CreateObject();
  7.     if (root == NULL) {
  8.         fprintf(stderr, "Failed to create JSON object\n");
  9.         return 1;
  10.     }
  11.     // 添加字符串类型的键值对
  12.     cJSON_AddStringToObject(root, "title", "Sample Document");
  13.     // 创建嵌套的 author 对象
  14.     cJSON *author = cJSON_CreateObject();
  15.     if (author == NULL) {
  16.         fprintf(stderr, "Failed to create author object\n");
  17.         cJSON_Delete(root);
  18.         return 1;
  19.     }
  20.     cJSON_AddStringToObject(author, "firstName", "Jane");
  21.     cJSON_AddStringToObject(author, "lastName", "Smith");
  22.     cJSON_AddItemToObject(root, "author", author);
  23.     // 创建 tags 数组
  24.     cJSON *tags = cJSON_CreateArray();
  25.     if (tags == NULL) {
  26.         fprintf(stderr, "Failed to create tags array\n");
  27.         cJSON_Delete(root);
  28.         return 1;
  29.     }
  30.     cJSON_AddItemToArray(tags, cJSON_CreateString("document"));
  31.     cJSON_AddItemToArray(tags, cJSON_CreateString("sample"));
  32.     cJSON_AddItemToObject(root, "tags", tags);
  33.     // 添加数字类型的键值对
  34.     cJSON_AddNumberToObject(root, "views", 1234);
  35.     // 添加布尔类型的键值对
  36.     cJSON_AddBoolToObject(root, "isPublished", 1);
  37.     // 将 JSON 对象转换为字符串
  38.     char *json_str = cJSON_Print(root);
  39.     if (json_str == NULL) {
  40.         fprintf(stderr, "Failed to print JSON object\n");
  41.         cJSON_Delete(root);
  42.         return 1;
  43.     }
  44.     // 打印 JSON 字符串
  45.     printf("%s\n", json_str);
  46.     // 释放内存
  47.     free(json_str);
  48.     cJSON_Delete(root);
  49.     return 0;
  50. }
复制代码

下面为你展示怎样利用 C 语言结合 cJSON 库,以文件形式读写和保存 JSON 数据。我们会提供两个示例,一个是从文件中读取 JSON 数据并解析,另一个是将生成的 JSON 数据保存到文件中。
1. 从文件读取并解析 JSON 数据
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "cJSON.h"
  5. // 从文件读取内容到字符串
  6. char* read_file(const char* filename) {
  7.     FILE* file = fopen(filename, "r");
  8.     if (file == NULL) {
  9.         perror("Failed to open file");
  10.         return NULL;
  11.     }
  12.     // 获取文件大小
  13.     fseek(file, 0, SEEK_END);
  14.     long size = ftell(file);
  15.     fseek(file, 0, SEEK_SET);
  16.     // 分配内存来存储文件内容
  17.     char* buffer = (char*)malloc(size + 1);
  18.     if (buffer == NULL) {
  19.         perror("Failed to allocate memory");
  20.         fclose(file);
  21.         return NULL;
  22.     }
  23.     // 读取文件内容
  24.     fread(buffer, 1, size, file);
  25.     buffer[size] = '\0';
  26.     fclose(file);
  27.     return buffer;
  28. }
  29. int main() {
  30.     const char* filename = "input.json";
  31.     char* json_str = read_file(filename);
  32.     if (json_str == NULL) {
  33.         return 1;
  34.     }
  35.     // 解析 JSON 字符串
  36.     cJSON* root = cJSON_Parse(json_str);
  37.     if (root == NULL) {
  38.         const char* error_ptr = cJSON_GetErrorPtr();
  39.         if (error_ptr != NULL) {
  40.             fprintf(stderr, "Error before: %s\n", error_ptr);
  41.         }
  42.         free(json_str);
  43.         return 1;
  44.     }
  45.     // 示例:获取并打印 "name" 字段的值
  46.     cJSON* name = cJSON_GetObjectItem(root, "name");
  47.     if (cJSON_IsString(name)) {
  48.         printf("Name: %s\n", name->valuestring);
  49.     }
  50.     // 释放资源
  51.     free(json_str);
  52.     cJSON_Delete(root);
  53.     return 0;
  54. }
复制代码
2. 生成 JSON 数据并保存到文件
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "cJSON.h"
  4. int main() {
  5.     // 创建根 JSON 对象
  6.     cJSON* root = cJSON_CreateObject();
  7.     if (root == NULL) {
  8.         fprintf(stderr, "Failed to create JSON object\n");
  9.         return 1;
  10.     }
  11.     // 添加键值对
  12.     cJSON_AddStringToObject(root, "name", "John Doe");
  13.     cJSON_AddNumberToObject(root, "age", 30);
  14.     // 将 JSON 对象转换为字符串
  15.     char* json_str = cJSON_Print(root);
  16.     if (json_str == NULL) {
  17.         fprintf(stderr, "Failed to print JSON object\n");
  18.         cJSON_Delete(root);
  19.         return 1;
  20.     }
  21.     // 打开文件以写入模式
  22.     FILE* file = fopen("output.json", "w");
  23.     if (file == NULL) {
  24.         perror("Failed to open file");
  25.         free(json_str);
  26.         cJSON_Delete(root);
  27.         return 1;
  28.     }
  29.     // 将 JSON 字符串写入文件
  30.     fputs(json_str, file);
  31.     // 关闭文件
  32.     fclose(file);
  33.     // 释放内存
  34.     free(json_str);
  35.     cJSON_Delete(root);
  36.     return 0;
  37. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

锦通

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表