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

news2025/3/31 22:33:21

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.coloradmin.cn/o/2303252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习整理安装php的uuid扩展以及uuid调用方法

学习整理安装php的uuid扩展以及uuid调用方法 1、安装uuid依赖库2、下载并安装3、ini中添加扩展4、re2c版本报错5、uuid调用方法 1、安装uuid依赖库 yum -y install uuid uuid-devel e2fsprogs-devel libuuid-devel2、下载并安装 点我下载uuid安装包 wget http://pecl.php.ne…

Orange 单体架构 - 快速启动

1 后端服务 1.1 基础设施 组件说明版本MySQLMySQL数据库服务5.7/8JavaJava17redis-stackRedis向量数据库最新版本Node安装Node22.11.0 1.2 orange-dependencies-parent 项目Maven依赖版本管理 1.2.1 项目克隆 GitHub git clone https://github.com/hengzq/orange-depende…

Spring Boot 入门 与 无法解析符号 springframework 的解决

Spring Boot 入门的关键步骤 1 创建 Maven 工程 操作目的&#xff1a; 通过 Maven 工程来管理项目依赖&#xff0c;Spring Boot 本身就依赖 Maven 或 Gradle 来简化依赖管理。 操作方法&#xff1a; 打开 IDEA&#xff08;IntelliJ IDEA&#xff09;。点击 New Project&#…

3D模型在线转换工具:轻松实现3DM转OBJ

3D模型在线转换是一款功能强大的在线工具&#xff0c;支持多种3D模型格式的在线预览和互转。无论是工业设计、建筑设计&#xff0c;还是数字艺术领域&#xff0c;这款工具都能满足您的需求。 3DM与OBJ格式简介 3DM格式&#xff1a;3DM是一种广泛应用于三维建模的文件格式&…

网络安全-js安全知识点与XSS常用payloads

简介 JavaScript 是一种轻量级的编程语言&#xff0c;定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系&#xff08;即没有关系&#xff09;。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…

ip属地是电话号码吗怎么改

在数字化时代&#xff0c;IP属地作为网络身份的一部分&#xff0c;对于许多互联网用户来说并不陌生。然而&#xff0c;关于IP属地的具体含义以及如何更改它&#xff0c;却常常让一些用户感到困惑。特别是当提到IP属地与电话号码之间的关系时&#xff0c;更是容易让人产生误解。…

Ubuntu中使用yum命令出现错误提示:Command ‘yum‘ not found

Ubuntu中使用yum命令出现以下错误提示: 解决方法如下 1、使用su或sudo -s命令使普通用户切换为root用户 2、然后检测是否安装了build-essential程序包,输入命令: apt-get install build-essential 3、进度走完后安装yum,输入命令: apt-get install yum 如果成功安装&#xff…

深入理解 JVM 的栈帧结构

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

[oeasy]python068_异常处理之后做些什么_try语句的完全体_最终_finally

068_异常处理之后做些什么_finally 异常处理之后做些什么_try语句的完全体_最终_finally 回忆上次内容 我们了解了 try 的细节 except 可以 捕获到异常 但报错比较简单 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 游乐场里面的 报错 更全 更丰富 …

PySide6学习专栏(四):用多线程完成复杂计算任务

如果计程序中要处理一个非常庞大的数据集中的数据&#xff0c;且数据处理计算很复杂&#xff0c;造成数据处理占用大量时间和CPU资源&#xff0c;如果不用多线程&#xff0c;仅在主进程中来处理数据&#xff0c;将会使整个程序卡死&#xff0c;必须采用多线程来处理这些数据是唯…

神经网络八股(1)

1.什么是有监督学习&#xff0c;无监督学习 有监督学习是带有标签的&#xff0c;无监督学习是没有标签的&#xff0c;简单来说就是有监督学习的输入输出都是固定的&#xff0c;已知的&#xff0c;无监督学习输入是已知的&#xff0c;输出是不固定的&#xff0c;无监督学习是通…

深度学习每周学习总结Y1(Yolov5 调用官方权重进行检测 )

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客Y1中的内容 &#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 ** 注意该训练营出现故意不退押金&#xff0c;恶意揣测偷懒用假的结果冒充真实打卡记录&#xff0c;在提出能够拿到视频录像…

计算机视觉基础|从 OpenCV 到频域分析

一、引言 在当今数字化时代&#xff0c;图像处理已渗透到我们生活的方方面面&#xff0c;从日常使用的智能手机拍照美化&#xff0c;到医学领域的精准诊断&#xff0c;再到自动驾驶中的环境感知&#xff0c;其重要性不言而喻。在图像处理领域中&#xff0c;OpenCV 和频域分析&…

74. 搜索二维矩阵(LeetCode 热题 100)

题目来源; 74. 搜索二维矩阵 - 力扣&#xff08;LeetCode&#xff09; 题目内容&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…

netcore libreoffice word转pdf中文乱码

一、效果 解决&#xff1a; cd /usr/share/fonts/ mkdir zhFont cd zhFont #windows系统C:\Windows\Fonts 中复制/usr/share/fonts/zhFont sudo apt update sudo apt install xfonts-utils mkfontscale mkfontdir #刷新字体缓存 fc-cache -fv #查看已安装的字体列表 fc-list :…

qt-C++笔记之创建和初始化 `QGraphicsScene` 和 `QGraphicsView` 并关联视图和场景的方法

qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 code review! 参考笔记 1.qt-C笔记之创建和初始化 QGraphicsScene 和 QGraphicsView 并关联视图和场景的方法 2.qt-C笔记之QGraphicsScene和 QGraphicsView中setScene、通过scene得到view、通过…

OpenGL 01--构建GLFW、创建第一个工程、配置GLAD

一、OpenGL介绍 一般它被认为是一个API(Application Programming Interface, 应用程序编程接口)&#xff0c;包含了一系列可以操作图形、图像的函数。然而&#xff0c;OpenGL本身并不是一个API&#xff0c;它仅仅是一个由Khronos组织制定并维护的规范(Specification)。 OpenGL规…

【时时三省】(C语言基础)求多项式1-1/2+1/3-1/4+...+1/99-1/100的值 用C语言表示

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 示例&#xff1a; 输出结果是 0.688172

kafka-集群缩容

一. 简述&#xff1a; 当业务增加时&#xff0c;服务瓶颈&#xff0c;我们需要进行扩容。当业务量下降时&#xff0c;为成本考虑。自然也会涉及到缩容。假设集群有 15 台机器&#xff0c;预计缩到 10 台机器&#xff0c;那么需要做 5 次缩容操作&#xff0c;每次将一个节点下线…

Ubuntu22.04 - etcd的安装和使用

目录 介绍安装Etcd安装etcd的客户端使用 介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统&#xff0c;用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性&#xff0c;且客户端通过长连接watch 功能&#xff0c;能够及时收到数据变化…