cJSON(C语言JSON)库(适用于嵌入式序列化和反序列化)

这篇具有很好参考价值的文章主要介绍了cJSON(C语言JSON)库(适用于嵌入式序列化和反序列化)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JSON与序列化和反序列化

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,它以易于阅读和编写的文本形式表示结构化数据。JSON 格式广泛用于将数据从一个应用程序传输到另一个应用程序,特别是在Web应用程序中,因为它与JavaScript兼容,容易在客户端和服务器之间进行数据交换。

JSON 数据由两种主要结构构成:

  1. 对象 (Object):对象由一对大括号 {} 包围,内部包含一个或多个键值对(key-value pairs)。每个键值对中,键是字符串,值可以是字符串、数字、布尔值、数组、对象或者 null。键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔。

    例如:

    {
        "name": "John",
        "age": 30,
        "isStudent": false
    }
    
  2. 数组 (Array):数组由一对方括号 [] 包围,内部包含一个或多个值,这些值可以是字符串、数字、布尔值、对象、数组或 null。数组中的值之间用逗号 , 分隔。

    例如:

    ["apple", "banana", "cherry"]
    

序列化和反序列化是将数据从一种格式转换为另一种格式的过程:

  1. 序列化:序列化是将数据结构(如对象或数组)转换为 JSON 字符串的过程。在编程中,这通常用于将数据转换为可以在网络上传输或存储在文件中的格式。

    例如,在JavaScript中,使用 JSON.stringify() 方法可以将一个对象或数组序列化为JSON字符串:

    const data = { name: "John", age: 30 };
    const jsonString = JSON.stringify(data);
    

    这将生成以下JSON字符串:

    {"name":"John","age":30}
    
  2. 反序列化:反序列化是将JSON字符串转换回原始数据结构的过程。这通常用于从网络或文件中读取JSON数据并将其还原为可供程序使用的数据结构。

    在JavaScript中,使用 JSON.parse() 方法可以将JSON字符串反序列化为原始对象或数组:

    const jsonString = '{"name":"John","age":30}';
    const data = JSON.parse(jsonString);
    

    这将把JSON字符串还原为一个包含相同数据的对象。

总之,JSON 是一种常用的数据格式,序列化和反序列化是将数据转换为JSON格式以及将其还原回原始数据结构的重要过程,用于数据交换和持久化存储。

cJSON(C语言JSON)库介绍

cJSON(C语言JSON)库是一个用于在C语言中解析和生成JSON数据的轻量级开源库。

仓库地址:

https://github.com/DaveGamble/cJSON

它提供了简单而强大的API,使C语言程序能够轻松地处理JSON数据。cJSON库的主要特点包括:

  1. 轻量级:cJSON库非常小巧,因此它不会增加太多的内存开销或二进制文件大小,适用于嵌入式系统和资源受限的环境。

  2. 易于使用:cJSON提供了一组简单的API函数,使用户能够轻松地解析和生成JSON数据。这些API包括创建JSON对象、数组、字符串、数字等,以及将JSON数据解析成C语言数据结构。

  3. 跨平台:cJSON库是跨平台的,可以在多种操作系统和编译器上运行,因此适用于各种C语言项目。

  4. 开源:cJSON是开源的,允许用户免费使用和修改它,符合自由软件和开源软件的原则。

  5. 支持标准的JSON格式:cJSON库支持标准的JSON格式,可以正确处理JSON对象、数组、字符串、数字、布尔值和null等基本JSON数据类型。

以下是cJSON库的一些基本用法示例:

创建JSON对象和添加键值对

cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "name", "John");
cJSON_AddNumberToObject(root, "age", 30);

创建JSON数组和添加元素

cJSON *array = cJSON_CreateArray();
cJSON_AddItemToArray(array, cJSON_CreateString("apple"));
cJSON_AddItemToArray(array, cJSON_CreateString("banana"));

将JSON数据解析成C语言数据结构

const char *jsonStr = "{\"name\":\"John\",\"age\":30}";
cJSON *root = cJSON_Parse(jsonStr);
const char *name = cJSON_GetObjectItem(root, "name")->valuestring;
int age = cJSON_GetObjectItem(root, "age")->valueint;

生成JSON字符串

char *jsonStr = cJSON_Print(root);

需要注意的是,使用cJSON库时,应该小心处理内存分配和释放,以避免内存泄漏。cJSON提供了一些用于释放JSON对象的函数,以确保在使用完JSON数据后正确释放相关内存。

cJSON库通常用于C语言项目中需要与JSON数据进行交互的情况,例如与API通信、配置文件解析和生成等。由于其轻量级和易用性,它在许多C语言应用程序中得到了广泛的应用。

cJSON(C语言JSON)库使用

下载出来的文件会有很多 但是真正用到的就是只有cJSON.h cJSON.c

appveyor.yml  cJSON.c  cJSON_Utils.c  CMakeLists.txt   fuzzing  LICENSE  README.md  tests
CHANGELOG.md  cJSON.h  cJSON_Utils.h  CONTRIBUTORS.md  library_config  Makefile  test.c valgrind.supp

将文件放到项目目录下 包含cJSON.h就可以使用了

序列化
常用函数介绍
  1. cJSON_AddNullToObject(cJSON * const object, const char * const name)

    • 功能:将一个null值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
    • 返回值:无。
  2. cJSON_AddTrueToObject(cJSON * const object, const char * const name)

    • 功能:将true值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
    • 返回值:无。
  3. cJSON_AddFalseToObject(cJSON * const object, const char * const name)

    • 功能:将false值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
    • 返回值:无。
  4. cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)

    • 功能:将布尔值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
      • boolean - 要添加的布尔值,非零表示true,零表示false。
    • 返回值:无。
  5. cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)

    • 功能:将数字值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
      • number - 要添加的双精度浮点数。
    • 返回值:无。
  6. cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)

    • 功能:将字符串值添加到JSON对象中。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
      • string - 要添加的C字符串。
    • 返回值:无。
  7. cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)

    • 功能:将原始JSON字符串添加到JSON对象中。这个方法允许您将已经是有效JSON的原始字符串添加到对象中,而不会进行额外的解析。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
      • raw - 要添加的原始JSON字符串。
    • 返回值:无。
  8. cJSON_AddObjectToObject(cJSON * const object, const char * const name)

    • 功能:创建一个新的JSON对象,并将其添加到父JSON对象中作为子对象。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
    • 返回值:无。
  9. cJSON_AddArrayToObject(cJSON * const object, const char * const name)

    • 功能:创建一个新的JSON数组,并将其添加到父JSON对象中作为子数组。
    • 参数:
      • object - 目标JSON对象。
      • name - 要添加的键的名称(C字符串)。
    • 返回值:无。
实例代码
#include<stdio.h>
#include"cJSON.h"

int main()
{
    cJSON* cjson_test = NULL;
    cJSON* cjson_address = NULL;
    cJSON* cjson_skill = NULL;
    char* str = NULL;

    /* 创建一个JSON数据对象(链表头结点) */
    cjson_test = cJSON_CreateObject();

    /* 添加一条字符串类型的JSON数据(添加一个链表节点) */
    cJSON_AddStringToObject(cjson_test, "name", "SysBent");

    /* 添加一条整数类型的JSON数据(添加一个链表节点) */
    cJSON_AddNumberToObject(cjson_test, "age", 22);

    /* 添加一条浮点类型的JSON数据(添加一个链表节点) */
    cJSON_AddNumberToObject(cjson_test, "weight", 55.5);

    /* 添加一个嵌套的JSON数据(添加一个链表节点) */
    cjson_address = cJSON_CreateObject();
    cJSON_AddStringToObject(cjson_address, "country", "China");
    cJSON_AddNumberToObject(cjson_address, "zip-code", 500000);
    cJSON_AddItemToObject(cjson_test, "address", cjson_address);

    /* 添加一个数组类型的JSON数据(添加一个链表节点) */
    cjson_skill = cJSON_CreateArray();
    cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "C/C++" ));
    cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Java" ));
    cJSON_AddItemToArray(cjson_skill, cJSON_CreateString( "Python" ));
    cJSON_AddItemToObject(cjson_test, "skill", cjson_skill);

    /* 添加一个值为 True 的布尔类型的JSON数据(添加一个链表节点) */
    cJSON_AddTrueToObject(cjson_test,"student");

    /* 打印JSON对象(整条链表)的所有数据 */
    str = cJSON_Print(cjson_test);
    printf("JSON String:\n%s\n", str);
    return 0;
}

编译并运行
c json,嵌入式中间件,STM32,ESP8266,嵌入式硬件,json,单片机

反序列化
常用函数介绍

在cJSON库中,反序d列化是指将JSON字符串解析为C语言数据结构的过程。cJSON库提供了一些函数来实现这个过程,其中最常用的函数是 cJSON_Parse()。以下是关于这个函数的详细解释以及其他相关函数:

  1. cJSON_Parse(const char *value)

    • 功能:将JSON字符串解析为相应的JSON对象或数组。
    • 参数:value - 包含JSON数据的C字符串。
    • 返回值:返回一个指向解析后的JSON对象或数组的指针。如果解析失败,返回NULL。

    示例:

    const char* json_str = "{\"name\":\"John\",\"age\":30}";
    cJSON* parsed_json = cJSON_Parse(json_str);
    if (parsed_json != NULL) {
        // 解析成功,可以继续操作解析后的JSON数据
        // ...
        cJSON_Delete(parsed_json); // 释放内存
    } else {
        // 解析失败,处理错误
        // ...
    }
    
  2. cJSON_GetObjectItem(const cJSON *object, const char *string)

    • 功能:获取JSON对象中指定键的值。
    • 参数:
      • object - 目标JSON对象。
      • string - 要获取值的键的名称(C字符串)。
    • 返回值:返回一个指向值的JSON对象或NULL(如果键不存在)。

    示例:

    const cJSON* name_item = cJSON_GetObjectItem(parsed_json, "name");
    if (name_item != NULL) {
        const char* name = name_item->valuestring;
        printf("Name: %s\n", name);
    }
    
  3. cJSON_GetArrayItem(const cJSON *array, int index)

    • 功能:获取JSON数组中指定索引位置的元素。
    • 参数:
      • array - 目标JSON数组。
      • index - 要获取的元素的索引(从0开始)。
    • 返回值:返回一个指向元素的JSON对象或NULL(如果索引越界)。

    示例:

    const cJSON* skill_item = cJSON_GetArrayItem(parsed_json, 0);
    if (skill_item != NULL) {
        const char* skill = skill_item->valuestring;
        printf("Skill 1: %s\n", skill);
    }
    
  4. cJSON_GetArraySize(const cJSON *array)

    • 功能:获取JSON数组的大小(元素数量)。
    • 参数:array - 目标JSON数组。
    • 返回值:返回数组的大小。

    示例:

    int array_size = cJSON_GetArraySize(parsed_json);
    printf("Array Size: %d\n", array_size);
    

这些函数使您能够在解析JSON字符串后,轻松地访问和提取JSON数据的值,以便在C语言程序中使用。要确保在使用完JSON数据后,通过 cJSON_Delete() 函数释放相关内存,以避免内存泄漏。

实例代码
#include <stdio.h>
#include "cJSON.h"

int main() {
    const char* json_str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";
    cJSON* parsed_json = cJSON_Parse(json_str);

    if (parsed_json != NULL) {
        // 从JSON对象中获取数据
        const char* name = cJSON_GetObjectItem(parsed_json, "name")->valuestring;
        int age = cJSON_GetObjectItem(parsed_json, "age")->valueint;
        const char* city = cJSON_GetObjectItem(parsed_json, "city")->valuestring;

        // 打印获取的数据
        printf("Name: %s\n", name);
        printf("Age: %d\n", age);
        printf("City: %s\n", city);

        // 释放内存
        cJSON_Delete(parsed_json);
    } else {
        printf("JSON parsing failed.\n");
    }

    return 0;
}

编译并运行
c json,嵌入式中间件,STM32,ESP8266,嵌入式硬件,json,单片机

使用注意事项

在使用cJSON库时,需要特别注意内存管理问题,以避免内存泄漏或内存溢出。以下是在使用cJSON库时可能涉及的一些内存问题和如何处理它们的建议:

  1. 内存分配

    • cJSON库在创建和操作JSON对象时会涉及内存分配。您需要确保在使用cJSON_CreateObject()cJSON_CreateArray() 和其他创建函数时分配足够的内存。
    • 在嵌入式系统中,资源可能有限,因此要小心分配内存的数量和时机,以避免耗尽内存。
  2. 释放内存

    • 在不再需要JSON对象时,应使用cJSON_Delete() 函数来释放内存。否则,可能会导致内存泄漏。
    • 确保释放嵌套的JSON对象以及数组元素的内存,以防止漏掉任何子对象。
  3. 释放序列化后的字符串内存

    • 使用cJSON_Print() 函数将JSON对象序列化为字符串后,需要负责释放字符串内存,以免出现内存泄漏。
    • 使用free() 函数释放这些字符串内存。
  4. 错误处理

    • 在分配内存和使用cJSON函数时,始终检查返回的指针是否为NULL。如果分配内存失败或解析JSON字符串失败,及时处理错误情况。
  5. 栈内存和堆内存

    • 考虑JSON对象的大小,小型JSON对象可以分配在栈上,而大型对象可能需要在堆上分配内存。要根据实际情况选择合适的内存分配方式。
  6. 嵌套和循环引用

    • 当涉及到嵌套JSON对象时,要小心处理循环引用。循环引用可能导致内存泄漏或无限递归。
    • 考虑使用引用计数或其他手段来管理嵌套对象的内存释放。
  7. 内存池

    • 对于资源受限的嵌入式系统,您可以考虑实现一个内存池来管理cJSON库的内存分配。这可以帮助您更好地控制和优化内存使用。

总之,在使用cJSON库时,良好的内存管理非常重要。要小心处理内存分配、释放和错误处理,以确保您的应用程序在处理JSON数据时不会出现内存问题。同时,根据您的应用需求,考虑使用适当的内存优化策略。
以下是一个示例代码,演示了如何使用cJSON库创建和释放JSON对象以及处理可能涉及的内存问题:

#include <stdio.h>
#include "cJSON.h"

int main() {
    // 创建一个JSON对象
    cJSON* cjson_object = cJSON_CreateObject();
    
    if (cjson_object != NULL) {
        // 添加键值对到JSON对象
        cJSON_AddStringToObject(cjson_object, "name", "John");
        cJSON_AddNumberToObject(cjson_object, "age", 30);
        
        // 序列化JSON对象为字符串
        char* json_str = cJSON_Print(cjson_object);
        printf("Serialized JSON:\n%s\n", json_str);
        
        // 释放序列化后的字符串内存
        free(json_str);
        
        // 释放JSON对象内存
        cJSON_Delete(cjson_object);
    } else {
        printf("Failed to create JSON object.\n");
    }

    return 0;
}

这个示例中,我们首先创建一个JSON对象 cjson_object,然后向它添加键值对。接下来,我们使用 cJSON_Print() 函数将JSON对象序列化为字符串,并使用 free() 函数释放序列化后的字符串内存。最后,我们使用 cJSON_Delete() 函数释放JSON对象的内存。

请注意,这个示例仅用于演示内存管理的基本原则。在实际应用中,您可能会处理更复杂的JSON结构,嵌套对象和数组,因此需要更复杂的内存管理策略来确保没有内存泄漏或错误。文章来源地址https://www.toymoban.com/news/detail-764942.html

到了这里,关于cJSON(C语言JSON)库(适用于嵌入式序列化和反序列化)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【嵌入式——C语言】共用体

    定义 :共用体和结构体类似,也是一种构造类型的数据结构,在进行某些算法时,需要使用几种不同类型的变量存到同一段内存单元中,几个变量所使用空间相互重叠,这几个不同的变量共同占用一段内存的结构,被称作共用体类型结构。 共用体的大小是其占内存长度最大

    2024年01月22日
    浏览(47)
  • 嵌入式C语言(入门必看)

          目录 STM32的数据类型 const static volatile extern  struct结构体 enum  typedef #define 回调函数 #ifdef 、#ifndef、#else  、#if     嵌入式开发中既有底层硬件的开发又涉及上层应用的开发,即涉及系统的硬件和软件,C语言既具有汇编语言操作底层的优势,又

    2024年01月17日
    浏览(44)
  • 【面试集锦 - 嵌入式软件 - C语言】

    指针函数(Pointer to a Function)和函数指针(Function Pointer)是在C和C++中经常使用的概念,它们虽然名称相似,但是在用法和作用上有一些区别。 指针函数 指针函数是指返回值为指针类型的函数。换句话说,它是一个函数,其返回类型是一个指针。指针函数可以用来实现动态分

    2024年02月07日
    浏览(52)
  • (嵌入式c语言)c语言编译常见错误

    预处理(gcc -E -o)-编译(gcc -S -o)-汇编(gcc -c -o)-链接(gcc -o) 将代码中的define 和 include替换成实体码  define和include不是,是在编译过程中处理的。 包含 #include 包含头文件 宏 #define 宏  替换  不会进行语法检查 #define 宏  宏体   宏体要加括号 #define ABC 

    2024年02月11日
    浏览(40)
  • 嵌入式C语言基础(STM32)

    前言:一条混迹嵌入式3年的老咸鱼,想到自己第一次接触到stm32的库函数时,c语言稀碎,痛不欲生的场景,该文章为萌新指条明路。 位操作在嵌入式中常用于直接对芯片的寄存器进行操作,当时作为初学者的我看着一脸懵逼,至于为什么这样修改,下面好好分析一下。  一

    2024年02月02日
    浏览(58)
  • 嵌入式学习之C语言指针部分复习

    今天主要把C语言的指针部分再次认真的复习了一下,对于指针的整体框架有了更加深刻的理解,特别要重点区分函数指针,指针函数,数组指针,指针数组部分,对于这部分的应用非常重要,而且C语言指针部分是面试的重中之重,所以要加强练习才行。 今天的学习是充满动

    2024年02月12日
    浏览(38)
  • MCU嵌入式开发-硬件和开发语言选择

    主要考虑以下方面来决定是否需要RTOS支持: 需要实现高响应时的多任务处理能力 需要实现实时性能要求高的任务 需要完成多个复杂的并发任务 具备满足工控系统实时性要求的各项功能特性。通过它提供的硬件库、线程支持、中断支持等,可以完全控制微控制器的各个外设,实

    2024年02月12日
    浏览(61)
  • 适合嵌入式C语言静态代码分析的工具

    收集了几个嵌入式C语言静态代码分析工具: Polyspace:Polyspace是MathWorks公司的一款静态代码分析工具,可以用于嵌入式C语言程序的静态分析。它可以检测代码中的缺陷、死代码、未定义行为等问题,并且支持多种编译器和操作系统。 LDRA:LDRA是一款商业化的静态代码分析工具

    2024年02月11日
    浏览(82)
  • 嵌入式深度学习语音分离降噪C语言实现

        加我微信hezkz17进数字音频系统研究开发交流答疑 一 深度学习在语音分离中的具体应用? 深度学习在语音分离中有多种具体应用。其中最常见的是使用深度神经网络(DNN)或卷积神经网络(CNN)进行语音分离任务。 1 一种应用是源分离,它旨在从混合语音信号中分离出单

    2024年02月13日
    浏览(73)
  • 嵌入式学习——C语言基础——day10

    1. 指针的基本概念 1.1 地址         用来区别不同内存字节空间的编号 1.2 指针         地址就是指针,指针就是地址,地址是一个编号,指针多了指向的概念 1.3 指针变量         用来存放指针的变量,有时将指针变量简称为指针 2. 指针相关运算符             ——   

    2024年04月27日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包