CJson源码解析之创建不同类型的键值对

文章目录

  • 前言
    • cJSON_CreateNull
    • cJSON_CreateTrue
    • cJSON_CreateFalse
    • cJSON_CreateBool
    • cJSON_CreateNumber
    • cJSON_CreateString
      • cJSON_strdup函数
      • cJSON_Delete函数
  • 总结


前言

在现代编程中,JSON已经成为了一种非常流行的数据交换格式。它的简洁性和易读性使得开发者可以轻松地在不同的系统和应用之间共享和理解数据。CJson是一个轻量级的JSON解析库,它提供了一种简单和高效的方式来解析和生成JSON数据。本文将深入探讨CJson的源码,特别是它如何创建不同类型的键值对。


这段代码比较简单,这里简单略过

cJSON_CreateNull

CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = cJSON_NULL;}return item;
}

在这个函数中,首先调用cJSON_New_Item函数来分配一个新的cJSON对象。如果内存分配成功,那么就将这个新对象的类型设置为cJSON_NULL,表示这个对象代表一个JSON null值。

cJSON_CreateTrue

CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = cJSON_True;}return item;
}

这个函数的实现与cJSON_CreateNull非常相似,唯一的区别是它将新对象的类型设置为cJSON_True,表示这个对象代表一个JSON true值。

cJSON_CreateFalse

CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = cJSON_False;}return item;
}

这个函数的实现也与cJSON_CreateNull非常相似,唯一的区别是它将新对象的类型设置为cJSON_False,表示这个对象代表一个JSON false值。

cJSON_CreateBool

CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = boolean ? cJSON_True : cJSON_False;}return item;
}

这个函数首先调用cJSON_New_Item函数来分配一个新的cJSON对象。然后,根据传入的布尔值参数,将新对象的类型设置为cJSON_TruecJSON_False

cJSON_CreateNumber

CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = cJSON_Number;item->valuedouble = num;/* use saturation in case of overflow */if (num >= INT_MAX){item->valueint = INT_MAX;}else if (num <= (double)INT_MIN){item->valueint = INT_MIN;}else{item->valueint = (int)num;}}return item;
}

这个函数首先调用cJSON_New_Item函数来分配一个新的cJSON对象。然后,将新对象的类型设置为cJSON_Number,并将传入的数字值赋给valuedouble成员。同时,它还处理了数字值的溢出情况。

cJSON_CreateString

CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
{cJSON *item = cJSON_New_Item(&global_hooks);if(item){item->type = cJSON_String;item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);if(!item->valuestring){cJSON_Delete(item);return NULL;}}return item;
}

这个函数首先调用cJSON_New_Item函数来分配一个新的cJSON对象。然后,将新对象的类型设置为cJSON_String,并将传入的字符串值复制到valuestring成员。如果字符串复制失败,那么就释放这个新对象,并返回NULL。

cJSON_strdup函数

static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
{size_t length = 0;unsigned char *copy = NULL;if (string == NULL){return NULL;}length = strlen((const char*)string) + sizeof("");copy = (unsigned char*)hooks->allocate(length);if (copy == NULL){return NULL;}memcpy(copy, string, length);return copy;
}

cJSON_strdup函数是cJSON库中的一个内部函数,它的作用是复制字符串。

在C语言中,字符串是通过字符数组来表示的,而复制字符串通常需要分配一块新的内存,然后将原字符串的内容复制到新的内存中。cJSON_strdup函数就是用来完成这个任务的。

cJSON_CreateString函数中,cJSON_strdup被用来复制传入的字符串值。这个复制的过程是必要的,因为我们不能保证传入的字符串在以后的使用中不会被修改或释放。通过复制字符串,我们可以确保cJSON对象中的字符串值是安全和稳定的。

需要注意的是,cJSON_strdup在内部调用了malloc为变量分配内存,所以在不需要使用返回的字符串时,需要用free释放相应的内存空间,否则会造成内存泄漏。

他的实现原理就是使用hooks->allocate复制出你需要的内存空间,然后memcpy把参数的内容复制进去仅此而已

cJSON_Delete函数

函数实现:

/* Delete a cJSON structure. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
{cJSON *next = NULL;while (item != NULL){next = item->next;if (!(item->type & cJSON_IsReference) && (item->child != NULL)){cJSON_Delete(item->child);}if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)){global_hooks.deallocate(item->valuestring);item->valuestring = NULL;}if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)){global_hooks.deallocate(item->string);item->string = NULL;}global_hooks.deallocate(item);item = next;}
}

这三个条件语句块是在处理cJSON对象的内存释放时使用的。具体来说:

  1. if (!(item->type & cJSON_IsReference) && (item->child != NULL)):这个条件语句块会在cJSON对象的child字段不为空,并且该对象不是对child的引用时执行。也就是说,如果这个cJSON对象拥有自己的child对象,那么在释放这个cJSON对象的内存时,也需要释放其child对象的内存。

  2. if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)):这个条件语句块会在cJSON对象的valuestring字段不为空,并且该对象不是对valuestring的引用时执行。也就是说,如果这个cJSON对象拥有自己的valuestring字符串,那么在释放这个cJSON对象的内存时,也需要释放其valuestring字符串的内存。

  3. if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)):这个条件语句块会在cJSON对象的string字段不为空,并且该字符串不是常量时执行。也就是说,如果这个cJSON对象拥有自己的string字符串,并且这个字符串可以修改,那么在释放这个cJSON对象的内存时,也需要释放其string字符串的内存。

在分支1中,递归cJSON_Delete,为什么要这样做?
因为我们并不知道一个child里面是单纯的键值对,还是有一堆对象和数组嵌套的,所以我们把child当作当个item去处理,这样就可以把最深层的键值对和其他的清除掉了。

最后一句怎么理解?


总结

通过深入研究CJson的源码和创建不同类型键值对的方法,我们可以更好地理解如何在JSON对象中添加和处理各种类型的数据。这些知识对于理解CJson的功能和性能至关重要。希望通过本文的阅读,你能对CJson有一个更深入的理解,也能在你的编程实践中更有效地使用JSON数据格式。未来,我们还将继续探索更多关于CJson的主题,包括它的性能优化,错误处理,以及如何在特定的应用场景中使用CJson。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/34886.shtml

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

相关文章

scikit-learn如何处理缺失数据?

scikit-learn处理缺失数据&#xff1a;方法与实践 在数据分析和机器学习项目中&#xff0c;处理缺失数据是一项常见且关键的任务。scikit-learn&#xff08;简称sklearn&#xff09;&#xff0c;作为Python中广泛使用的机器学习库&#xff0c;提供了多种工具和技术来帮助我们处…

ros创建deb功能包安装文件

1、在功能包下执行&#xff1a; bloom-generate rosdebian --os-name ubuntu --ros-distro noetic2、执行&#xff1a; fakeroot debian/rules binary 生成的文件在上级目录。

Linux_应用篇(27) CMake 入门与进阶

在前面章节内容中&#xff0c;我们编写了很多示例程序&#xff0c;但这些示例程序都只有一个.c 源文件&#xff0c;非常简单。 所以&#xff0c;编译这些示例代码其实都非常简单&#xff0c;直接使用 GCC 编译器编译即可&#xff0c;连 Makefile 都不需要。但是&#xff0c;在实…

神经网路学习7-线性模型

一个最简单的线性模型&#xff0c;w是权重&#xff0c;一般来说会取随机值&#xff0c;然后不断学习直到与预期相同 如此以此取每个值与真实值的差值&#xff0c;即评估误差 即找一个合适的权重w&#xff0c;使得平均误差最小 上面的是针对单个样本的&#xff0c;后面的是对…

malloc、free和new delete的区别

malloc/free 和 new/delete 是在 C 中分配和释放内存的两种不同方法。它们主要有以下区别&#xff1a; 1. 语法和用法 malloc 和 free: malloc开辟空间时需要手动计算分配的空间大小 int* p (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存 // 使用内存 free(p); …

2024年必备的15个免费 SVG 设计资源

在动态设计领域&#xff0c;SVG&#xff08;可缩放矢量图形&#xff09;已成为设计师打造响应迅速、清晰且适应性强的视觉效果的必备工具。 这些设计非常适合幻灯片 PowerPoint 演示文稿、应用程序设计、网站设计、原型设计、社交媒体帖子等。 在这篇文章中&#xff0c;我们将…

让GNSSRTK不再难【第13讲】

第13讲 仿距差分定位原理-站间单差 从单点定位的定位流程中,我们了解到卫星的轨道、钟差以及大气都存在误差,这是导致单点定位精度不佳的原因。所以我们再次列出伪距的观测值表达式。 P r , i s = ρ r , i s − c δ t s + c δ t r , i + I r , i s + T r , i s + d r , i…

【ONLYOFFICE8.1桌面编辑器】强势来袭—— 一款全面的办公软件套件

在日常工作和学习中&#xff0c;我们经常需要处理各种文档、表格和演示文稿。一款功能强大、易于使用的办公软件成为我们提高工作效率、便捷沟通和展示想法的得力助手。 而ONLYOFFICE 8.1桌面编辑器正是一款全面、高效的办公软件&#xff0c;集合了Word、PPT、Excel的功能&…

20240626 每日AI必读资讯

&#x1f30d;警告&#xff01;OpenAI宣布全面封锁中国API接入&#xff01; - 7月9号开始封锁不支持的国家API - 如果在OpenAI不允许的国家使用其 API 将面临封杀 &#x1f517; 警告&#xff01;OpenAI 宣布全面封锁中国 API 接入-CSDN博客 &#x1f3b5;索尼、环球音乐、华…

基于SpringBoot的“智慧食堂”管理系统设计与实现

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootVue 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 用户管理界面 菜品…

【C# | 分析器】禁止子类在覆写父类虚方法时调用父类方法实现

此分析器功能比较简陋&#xff0c;仅作个人备忘。 参考资料&#xff1a;https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix 将以下分析器代码编译为DLL后&#xff0c;将DLL添加到项目分析器列表中&#xff0c;即可…

基于CRITIC-TOPSIS法的各地区评价

1.CRITIC-TOPSIS法原理 1.1 基本理论 CRITIC-TOPSIS法是一种结合CRITIC&#xff08;Criteria Importance Through Intercriteria Correlation&#xff09;法和TOPSIS&#xff08;Technique for Order Preference by Similarity to Ideal Solution&#xff09;法的综合评价方法…

深度学习语义分割算法之基础知识

文章目录 前言一、图像分割介绍1.语义分割2.实例分割3.全景分割 二、常见数据集格式1.PASCAL VOC2.MS COCO 三、语义分割结果四、语义分割常见评价指标1.Pixel Accuracy2.mean Accuracy3.mean IoU 五、语义分割标注工具结束语 &#x1f482; 个人主页:风间琉璃&#x1f91f; 版…

Python 入门 —— 描述器

Python 入门 —— 描述器 文章目录 Python 入门 —— 描述器描述器简单示例定制名称只读属性状态交互验证器类自定义验证器验证器的使用 对象关系映射 描述器 前面我们介绍了两种属性拦截的方式&#xff1a;特性&#xff08;property&#xff09;以及重载属性访问运算符&#…

更适合敏感口腔的护理牙刷

最近在用一款清九野小红盾舒敏牙刷&#xff0c;感觉它很适合牙龈敏感的人&#xff0c;让刷牙体验有了显著的提升。这款牙刷的柔软刷毛和精细设计让我的刷牙过程变得轻松愉快。它的内外圈双重植毛技术&#xff0c;在清洁牙齿的同时&#xff0c;还能深入牙缝&#xff0c;温和地去…

设计模式原则——单一职责原则(SPS)

设计模式原则 设计模式示例代码库地址&#xff1a; https://gitee.com/Jasonpupil/designPatterns 单一职责原则&#xff08;SPS&#xff09;&#xff1a; 又称单一功能原则&#xff0c;面向对象五个基本原则&#xff08;SOLID&#xff09;之一原则定义&#xff1a;一个类应…

linux启动jar包,提示jvm内存不足

出现场景 服务器内存还剩余很多&#xff0c;但是启动jar报内存不足 Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007f66434f0000, 65536, 1) failed; error无法分配内存 (errno12) [thread 140076481570560 also had an error] # # Compiler re…

基于Docker的淘客返利平台部署

基于Docker的淘客返利平台部署 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在本文中&#xff0c;我们将探讨如何利用Docker技术来部署一个淘客返利平台。Doc…

还能这样执行命令?命令执行绕过及防护规则研究

一、引言 我是渗透工程师->很多小伙伴在做攻防实战时发现有时在命令执行的payload中穿插单双引号命令也能执行成功&#xff0c;有时却又不行。那么到底在什么条件下用什么样的方式能实现对命令的切分呢&#xff1f;其中的原理又是如何&#xff1f;有没有其他绕过方式&#…

openlayers 轨迹回放(历史轨迹),实时轨迹

本篇介绍一下使用openlayers轨迹回放&#xff08;历史轨迹&#xff09;&#xff0c;实时轨迹 1 需求 轨迹回放&#xff08;历史轨迹&#xff09;实时轨迹 2 分析 主要是利用定时器&#xff0c;不断添加feature 轨迹回放&#xff08;历史轨迹&#xff09;&#xff0c;一般是…