云计算百科
云计算领域专业知识百科平台

C/C++ 使用cJSON库实现结构体和json字符串相互序列化

C/C++ 使用cJSON库实现结构体和json字符串相互序列化

  • 一、什么是json
    • 1、核心特性
    • 2、应用场景
    • 3、示例解析
    • 4、注意事项
  • 二、cJSON库介绍
    • 1、 概述
    • 2、 核心功能
    • 3、主要特点
    • 4、 数据结构
    • 5、基本使用流程
  • 三、结构体和json字符串互转
    • 1、下载源码
    • 2、使用方法

在这里插入图片描述

一、什么是json

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于网络数据传输和配置文件。它采用人类可读的文本格式,基于JavaScript对象语法,但独立于编程语言(几乎所有主流语言都支持JSON解析)。

1、核心特性

  • 结构清晰

    • 键值对集合:{ "name": "Alice", "age": 30 }
    • 有序列表:[ "apple", "banana", "cherry" ]
    • 支持嵌套:{
      "user": {
      "id": 123,
      "preferences": ["reading", "hiking"]
      }
      }
  • 数据类型

    • 字符串:"hello"
    • 数字:42 或 3.14
    • 布尔值:true/false
    • 空值:null
    • 数组:[1, 2, 3]
    • 对象:{"key": "value"}
  • 语法规则

    • 键名必须用双引号包裹
    • 字符串必须用双引号
    • 不允许注释或尾随逗号
  • 2、应用场景

    • API通信:前后端数据交互(如RESTful API)
    • 配置文件:package.json(Node.js)、tsconfig.json(TypeScript)
    • 数据存储:NoSQL数据库(如MongoDB)的文档格式
    • 日志记录:结构化日志文件

    3、示例解析

    {
    "course": "计算机科学",
    "credits": 4,
    "prerequisites": ["编程基础", "离散数学"],
    "active": true
    }

    对应JavaScript对象:

    const courseInfo = {
    course: "计算机科学",
    credits: 4,
    prerequisites: ["编程基础", "离散数学"],
    active: true
    };

    4、注意事项

  • 安全风险 直接解析不可信来源的JSON可能导致注入攻击(如JSON.parse()执行恶意代码)。
  • 格式校验 使用工具如JSON Schema验证结构合法性。
  • 解析差异 某些语言(如Python)的json模块会将数字解析为浮点数而非整数。
  • 二、cJSON库介绍

    1、 概述

    cJSON 是一个轻量级、开源的 C 语言 JSON 解析库。它专注于提供简单、快速且易于使用的接口,用于在 C 语言程序中解析、生成和操作 JSON (JavaScript Object Notation) 数据。JSON 是一种轻量级的数据交换格式,广泛用于网络通信、配置文件存储等场景。

    2、 核心功能

    cJSON 提供以下核心功能:

    • 解析 JSON: 将 JSON 格式的字符串解析成 cJSON 提供的数据结构(通常是 cJSON 对象),以便程序能够读取其中的数据。
    • 生成 JSON: 将程序中的数据结构(cJSON 对象)序列化成符合 JSON 规范的字符串,便于传输或存储。
    • 访问数据: 提供 API 用于遍历和访问解析后的 JSON 对象中的键值对、数组元素等。
    • 修改数据: 支持在解析后的结构体上添加、修改或删除元素。
    • 打印格式化: 可以将 cJSON 对象以格式化的(易读)或非格式化的(紧凑)方式打印成 JSON 字符串。

    3、主要特点

    • 轻量级: cJSON 的源代码非常精简,通常只有一个 .c 文件和一个 .h 头文件。这使得它易于集成到项目中,尤其适合资源受限的环境(如嵌入式系统)。
    • 纯 C 实现: 完全用 C 语言编写,不依赖外部库(除标准 C 库外),具有良好的可移植性。
    • 简单易用: API 设计相对简洁明了。核心数据结构通常是 struct cJSON,通过一系列函数(如 cJSON_Parse, cJSON_GetObjectItem, cJSON_CreateObject, cJSON_Print 等)进行操作。
    • 链式存储: 内部使用链表来管理 JSON 对象中的成员和数组中的元素。
    • 内存管理: 库负责在解析时分配内存(通常在堆上),并提供了释放整个解析树内存的函数(cJSON_Delete)。使用者需要负责管理输入字符串和输出字符串的内存。

    4、 数据结构

    cJSON 库的核心是 cJSON 结构体(通常在 cJSON.h 中定义),它用来表示 JSON 数据中的各种类型(对象、数组、字符串、数字、布尔值、null)。这个结构体通常包含以下成员(具体实现可能略有差异):

    • type: 表示该节点的 JSON 数据类型(如 cJSON_Object, cJSON_Array, cJSON_String, cJSON_Number 等)。
    • valuestring: 当类型是字符串时,存储字符串值(对于数字类型,可能存储其字符串表示)。
    • valueint, valuedouble: 存储整数值或浮点数值(取决于解析方式和配置)。
    • child: 对于对象或数组类型,指向其第一个子节点(对象成员或数组元素)。
    • next, prev: 用于在链表(对象成员链表或数组元素链表)中连接兄弟节点。
    • string: 对于对象中的成员,存储该成员的键名。

    5、基本使用流程

  • 解析 JSON:const char *json_string = "{\\"name\\":\\"Alice\\",\\"age\\":30}";
    cJSON *root = cJSON_Parse(json_string);
    if (root == NULL) {
    const char *error_ptr = cJSON_GetErrorPtr();
    if (error_ptr != NULL) {
    fprintf(stderr, "Error before: %s\\n", error_ptr);
    }
    // 处理解析错误
    }
  • 访问数据:cJSON *name = cJSON_GetObjectItemCaseSensitive(root, "name");
    if (cJSON_IsString(name)) {
    printf("Name: %s\\n", name->valuestring);
    }
    cJSON *age = cJSON_GetObjectItemCaseSensitive(root, "age");
    if (cJSON_IsNumber(age)) {
    printf("Age: %d\\n", age->valueint); // 或者 age->valuedouble
    }
  • 生成 JSON:cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "name", "Bob");
    cJSON_AddNumberToObject(root, "age", 25);
    char *json_output = cJSON_Print(root); // 格式化输出
    // char *json_output = cJSON_PrintUnformatted(root); // 紧凑输出
    printf("%s\\n", json_output);
    // 使用完后释放输出字符串
    free(json_output);
  • 释放资源:cJSON_Delete(root); // 释放整个解析树占用的内存
  • 三、结构体和json字符串互转

    1、下载源码

    点击下载

    2、使用方法

    /** 项目结构体 */
    struct project
    {
    int id;
    char *name;
    };

    /** 仓库结构体 */
    struct hub
    {
    int id;
    char *user;
    struct project *cson;
    };

    /** 项目结构体数据模型 */
    CsonModel projectModel[] =
    {
    CSON_MODEL_OBJ(struct project),
    CSON_MODEL_INT(struct project, id),
    CSON_MODEL_STRING(struct project, name),
    };

    /** 仓库结构体数据模型 */
    CsonModel hubModel[] =
    {
    CSON_MODEL_OBJ(struct hub),
    CSON_MODEL_INT(struct hub, id),
    CSON_MODEL_STRING(struct hub, user),
    CSON_MODEL_STRUCT(struct hub, cson, projectModel, sizeof(projectModel)/sizeof(CsonModel))
    };

    void csonDemo(void)
    {
    char *jsonDemo = "{\\"id\\": 1, \\"user\\": \\"Letter\\", \\"cson\\": {\\"id\\": 2, \\"name\\": \\"cson\\"}}";

    /** 解析json */
    struct hub *pHub = csonDecode(jsonDemo, hubModel, sizeof(hubModel)/sizeof(CsonModel));
    printf("hub: id: %d, user: %s, project id: %d, project name: %s\\r\\n",
    pHub->id, pHub->user, pHub->cson->id, pHub->cson->name);

    /** 序列化对象 */
    char *formatJson = csonEncode(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel), 512, 1);
    printf("format json: %s\\r\\n", formatJson);

    /** 释放结构体对象 */
    csonFree(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));

    /** 释放序列化生成的json字符串 */
    csonFreeJson(formatJson);
    }

    运行结果

    hub: id: 1, user: Letter, project id: 2, project name: cson
    format json: {
    "id": 1,
    "user": "Letter",
    "cson": {
    "id": 2,
    "name": "cson"
    }
    }

    在这里插入图片描述

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » C/C++ 使用cJSON库实现结构体和json字符串相互序列化
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!