当前位置: 首页 > article >正文

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

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;
}
  1. 生成 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;
}

http://www.kler.cn/a/555416.html

相关文章:

  • Git如何将一个分支的内容同步到另一个分支
  • C# SpinLock 类 使用详解
  • 知识库管理系统驱动企业知识体系重构与智能协作路径解析
  • 大数据治理之solr的体现
  • 03.Docker 命令帮助
  • 鸿蒙-状态管理V1
  • 鸿蒙初学者学习手册(HarmonyOSNext_API14)_自定义动画API(@ohos.animator (动画) )
  • 由浅入深学习大语言模型RLHF(PPO强化学习- v1浅浅的)
  • 人工智能丨OCR 的业务场景,实现原理和测试指标
  • 【开源商城系统是否能直接拿去售卖】
  • 鸿蒙-自定义相机拍照
  • rapidfuzz进阶应用:让模糊匹配更上一层楼,解锁更强大的字符串处理能力!
  • 具身智能在智能巡检机器人中的应用——以开关柜带电操作机器人为例
  • Python 函数-调用函数
  • SearXNG——自建一个属于自己的免费搜索引擎平台
  • 软件需求类的论文无法量化评价的问题
  • 深度解读Grok-2:新一代AI大模型的崛起
  • 【OS安装与使用】part3-ubuntu安装Nvidia显卡驱动+CUDA 12.4
  • 【登月计划】 DAY2 中期:产品研发与设计验证(4-6)--《设计图纸如何从电脑飞进生产线?揭秘研发系统的 “暗箱操作”》
  • 苍穹外卖day8 地址上传 用户下单 订单支付