JSON 和 cJSON 库入门教程
第一部分:了解 JSON (JavaScript Object Notation)
-
什么是 JSON?
- JSON 是一种轻量级的数据交换格式。
- 它易于人阅读和编写,同时也易于机器解析和生成。
- JSON 基于 JavaScript 编程语言的一个子集,但它是一种独立于语言的文本格式。许多编程语言都有解析和生成 JSON 数据的库。
-
JSON 的基本结构
JSON 数据由两种基本结构组成:- 对象 (Object):
- 表示为
{}
(花括号)包裹的无序的键/值对 (key/value pairs)集合。 - 键 (key) 必须是字符串(用双引号
""
包裹)。 - 值 (value) 可以是字符串、数字、布尔值 (
true
/false
)、数组、另一个 JSON 对象,或者null
值。 - 键和值之间用冒号
:
分隔,键值对之间用逗号,
分隔。 - 示例:
{"name": "ESP32","cores": 2,"isWireless": true }
- 表示为
- 数组 (Array):
- 表示为
[]
(方括号)包裹的有序的值的集合。 - 值之间用逗号
,
分隔。 - 数组中的值可以是不同类型的。
- 示例:
{"sensors": ["temperature", "humidity", "pressure"],"ports": [80, 443, 1883] }
- 表示为
- 对象 (Object):
-
JSON 数据类型
- 字符串 (String):由双引号
""
包裹的 Unicode 字符序列。例如:"hello"
,"main.c"
。 - 数字 (Number):整数或浮点数。例如:
101
,-5.5
,3.14159e-2
。 - 布尔值 (Boolean):
true
或false
。 null
:表示空值或无值。- 对象 (Object):如上所述,键值对的集合。
- 数组 (Array):如上所述,值的有序列表。
- 字符串 (String):由双引号
-
一个完整的 JSON 示例
下面是一个更复杂的 JSON 示例,结合了对象和数组:{"deviceName": "SmartLight_01","location": "Living Room","status": {"isOn": true,"brightness": 75,"colorRGB": [255, 255, 0]},"supportedModes": ["Normal", "Night", "Reading"],"firmwareVersion": null }
在这个例子中:
- 最外层是一个 JSON 对象。
"deviceName"
的值是一个字符串。"status"
的值是另一个 JSON 对象。"colorRGB"
(在"status"
对象内部) 的值是一个包含三个数字的数组。"supportedModes"
的值是一个包含三个字符串的数组。"firmwareVersion"
的值是null
。
第二部分:cJSON 库入门 (C 语言处理 JSON)
-
什么是 cJSON?
- cJSON 是一个用标准 ANSI C 编写的超轻量级 JSON 解析器和生成器。
- 它的设计目标是小巧、快速且易于使用,非常适合在资源受限的系统(如微控制器 ESP32)上处理 JSON 数据。
-
为什么在 C 语言中使用 cJSON?
- 解析 (Parsing):当你的 C 程序接收到一个 JSON 格式的字符串(例如,从网络、文件或传感器),cJSON 可以帮助你将这个字符串转换成 C 语言可以理解和操作的数据结构。
- 生成 (Generating):当你的 C 程序需要发送 JSON 格式的数据时,cJSON 可以帮助你将 C 语言中的数据结构转换成 JSON 格式的字符串。
- 操作 (Manipulating):一旦 JSON 被解析,你可以使用 cJSON 提供的函数来访问、检查和修改数据。
-
cJSON 的核心概念:
cJSON
结构体- 在 cJSON 中,所有 JSON 元素(无论是对象、数组、字符串、数字还是布尔值)都被表示为一个指向
cJSON
结构体的指针 (cJSON*
)。 - 这个结构体内部有一个
type
字段,它指明了该 cJSON 节点代表的 JSON 数据类型(例如cJSON_Object
,cJSON_Array
,cJSON_String
,cJSON_Number
,cJSON_True
,cJSON_False
,cJSON_NULL
)。
- 在 cJSON 中,所有 JSON 元素(无论是对象、数组、字符串、数字还是布尔值)都被表示为一个指向
/* cJSON Types: */ #define cJSON_Invalid (0) #define cJSON_False (1 << 0) #define cJSON_True (1 << 1) #define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) #define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) #define cJSON_Raw (1 << 7) /* raw json *//* The cJSON structure: */ typedef struct cJSON {/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *next;struct cJSON *prev;/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */struct cJSON *child;/* The type of the item, as above. */int type;/* The item's string, if type==cJSON_String and type == cJSON_Raw */char *valuestring;/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */int valueint;/* The item's number, if type==cJSON_Number */double valuedouble;/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */char *string; } cJSON;
根据类型的不同,结构体中还有其他字段来存储实际的值(如 valuestring
存字符串,valueint
和 valuedouble
存数字)。
-
cJSON 主要函数和用法
首先,你需要在使用 cJSON 的 C 文件中包含其头文件:
#include "cJSON.h"
-
解析 JSON 字符串 ->
cJSON
对象
cJSON* cJSON_Parse(const char *value);
这个函数接收一个 JSON 格式的 C 字符串,并尝试将其解析成一个cJSON
对象树。- 如果解析成功,它返回指向树的根节点的
cJSON*
指针。 - 如果解析失败(例如 JSON 格式错误),它返回
NULL
。你可以用cJSON_GetErrorPtr()
获取错误发生的大致位置。
- 如果解析成功,它返回指向树的根节点的
-
重要:
cJSON_Parse
创建的cJSON
对象及其所有子节点都会分配内存。使用完毕后,必须调用cJSON_Delete()
来释放这些内存,以避免内存泄漏。const char *json_data_string = "{\"sensor\":\"temperature\", \"value\":25.5, \"unit\":\"C\"}"; cJSON *root = cJSON_Parse(json_data_string);if (root == NULL) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}// 处理解析错误... } else {// 解析成功,可以开始使用 root// ... }
* **释放 `cJSON` 对象内存**`void cJSON_Delete(cJSON *item);`这个函数会递归地释放 `item` 指向的 `cJSON` 对象及其所有子节点占用的内存。```c// ... 使用完 root 后 ...cJSON_Delete(root);root = NULL; // 良好习惯,防止悬挂指针
-
访问 JSON 对象中的成员
cJSON* cJSON_GetObjectItem(const cJSON *object, const char *string);
或者大小写不敏感的版本:cJSON* cJSON_GetObjectItemCaseSensitive(const cJSON *object, const char *string);
(通常用前者)
这个函数从一个cJSON_Object
类型的节点中,根据键名(一个 C 字符串)查找对应的成员。- 如果找到,返回指向该成员的
cJSON*
指针。
- 如果找到,返回指向该成员的
-
如果未找到,返回
NULL
。// 假设 root 指向上面解析得到的 {"sensor":"temperature", "value":25.5, "unit":"C"} cJSON *sensor_item = cJSON_GetObjectItem(root, "sensor"); cJSON *value_item = cJSON_GetObjectItem(root, "value"); cJSON *unit_item = cJSON_GetObjectItem(root, "unit");// 检查类型并获取值 if (sensor_item != NULL && cJSON_IsString(sensor_item)) {printf("Sensor Type: %s\n", sensor_item->valuestring); } if (value_item != NULL && cJSON_IsNumber(value_item)) {printf("Value: %f\n", value_item->valuedouble); // 或者 value_item->valueint (如果是整数) } if (unit_item != NULL && cJSON_IsString(unit_item) && unit_item->valuestring != NULL) {printf("Unit: %s\n", unit_item->valuestring); }
-
访问 JSON 数组中的元素
cJSON* cJSON_GetArrayItem(const cJSON *array, int index);
获取数组中指定索引处的元素。索引从 0 开始。
int cJSON_GetArraySize(const cJSON *array);
获取数组中元素的数量。// 假设 json_array_string = "{\"values\":[10, 20, 30]}" // cJSON *root_array_obj = cJSON_Parse(json_array_string); // cJSON *values_array = cJSON_GetObjectItem(root_array_obj, "values"); // if (values_array != NULL && cJSON_IsArray(values_array)) { // int size = cJSON_GetArraySize(values_array); // for (int i = 0; i < size; i++) { // cJSON *element = cJSON_GetArrayItem(values_array, i); // if (element != NULL && cJSON_IsNumber(element)) { // printf("Array element %d: %d\n", i, element->valueint); // } // } // } // cJSON_Delete(root_array_obj);
-
检查节点类型
cJSON 提供了一系列cJSON_Is<Type>()
函数来检查一个cJSON
节点的类型:cJSON_IsObject(const cJSON * const item)
cJSON_IsArray(const cJSON * const item)
cJSON_IsString(const cJSON * const item)
cJSON_IsNumber(const cJSON * const item)
cJSON_IsTrue(const cJSON * const item)
cJSON_IsFalse(const cJSON * const item)
cJSON_IsBool(const cJSON * const item)
(检查是True
或False
)cJSON_IsNull(const cJSON * const item)
在使用valuestring
,valueint
,valuedouble
之前,务必先用这些函数检查类型,以避免错误。
-
获取节点的值
一旦确定了类型,你可以通过cJSON
结构体的成员访问其实际值:item->valuestring
: (类型是char*
) 对于字符串节点。item->valueint
: (类型是int
) 对于数字节点(通常是整数部分)。item->valuedouble
: (类型是double
) 对于数字节点(浮点数值)。- 对于布尔值,直接使用
cJSON_IsTrue()
或cJSON_IsFalse()
判断。
-
创建 JSON 结构
你也可以从零开始构建 JSON 结构:cJSON* cJSON_CreateObject(void);
cJSON* cJSON_CreateArray(void);
cJSON* cJSON_CreateString(const char *string);
cJSON* cJSON_CreateNumber(double num);
cJSON* cJSON_CreateBool(cJSON_bool boolean);
(传入1
代表true
,0
代表false
)cJSON* cJSON_CreateNull(void);
-
向对象/数组中添加成员
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
(将item
添加到object
中,键为string
)void cJSON_AddItemToArray(cJSON *array, cJSON *item);
(将item
添加到array
的末尾)- 注意:当一个
cJSON
节点通过这些函数被添加到另一个节点(父节点)后,它的内存管理就由父节点负责了。你不需要单独删除这个被添加的子节点;它会在父节点被cJSON_Delete()
时一起被删除。 - 还有一些便捷的宏,例如:
cJSON_AddStringToObject(object, "key", "value_string");
cJSON_AddNumberToObject(object, "key", 123);
cJSON *new_json_obj = cJSON_CreateObject(); if (!new_json_obj) { /* error handling */ }cJSON_AddStringToObject(new_json_obj, "command", "SET_LED"); cJSON_AddNumberToObject(new_json_obj, "led_id", 1); cJSON_AddTrueToObject(new_json_obj, "state"); // state: truecJSON *params_array = cJSON_CreateArray(); if (!params_array) { /* error handling */ cJSON_Delete(new_json_obj); return; } cJSON_AddItemToArray(params_array, cJSON_CreateNumber(255)); cJSON_AddItemToArray(params_array, cJSON_CreateNumber(0)); cJSON_AddItemToArray(params_array, cJSON_CreateNumber(0)); // color red cJSON_AddItemToObject(new_json_obj, "color_rgb", params_array); // 添加数组到对象// 现在 new_json_obj 代表: {"command":"SET_LED", "led_id":1, "state":true, "color_rgb":[255,0,0]}
-
将
cJSON
对象转换回 JSON 字符串char* cJSON_Print(const cJSON *item);
:生成带格式(易读,有换行和缩进)的 JSON 字符串。char* cJSON_PrintUnformatted(const cJSON *item);
:生成不带格式(紧凑,无额外空白)的 JSON 字符串。在网络传输时,通常用这个来节省带宽。- 重要: 这两个函数返回的字符串是动态分配内存的(使用
malloc
)。你必须在使用完毕后调用free()
(或者cJSON_free()
,它们通常是等价的) 来释放这块内存。
// ... 接上一个创建的 new_json_obj ... char *formatted_string = cJSON_Print(new_json_obj); if (formatted_string) {printf("Formatted JSON:\n%s\n", formatted_string);free(formatted_string); // 或者 cJSON_free(formatted_string) }char *unformatted_string = cJSON_PrintUnformatted(new_json_obj); if (unformatted_string) {printf("Unformatted JSON: %s\n", unformatted_string);// 通常这个字符串用于发送到网络或保存free(unformatted_string); // 或者 cJSON_free(unformatted_string) }cJSON_Delete(new_json_obj); // 最后删除 cJSON 对象本身
-
-
在你的
main.c
中的应用举例 (parse_m2m_message
函数)
给出一个示例,一个自定义函数parse_m2m_message
函数是如何使用 cJSON 的:// static int parse_m2m_message(const char *data, int data_len) // {// ...// char *data_copy = (char *)calloc(data_len + 1, sizeof(char)); // 创建数据副本// memcpy(data_copy, data, data_len);// data_copy[data_len] = '\0'; // 确保NULL结尾//// cJSON *root = cJSON_Parse(data_copy); // 1. 解析JSON字符串// if (root == NULL) { /* 错误处理 */ free(data_copy); return 0; }//// cJSON *from = cJSON_GetObjectItem(root, "from"); // 2. 获取对象成员// if (!from || !cJSON_IsString(from)) { /* 错误处理 */ }// printf("消息来源设备: %s\n", from->valuestring); // 3. 获取字符串值//// cJSON *cmd = cJSON_GetObjectItem(root, "cmd");// if (cmd && cJSON_IsString(cmd)) {// cJSON *value = cJSON_GetObjectItem(root, "value");// if (!value || !cJSON_IsNumber(value)) { /* 错误处理 */ }// printf("收到命令类型: %s, 命令值: %d\n", cmd->valuestring, value->valueint); // 获取数字值// // ... 进一步处理命令 ...// }// ...// cJSON_Delete(root); // 4. 释放内存// free(data_copy);// return 1; // }
这个函数清晰地展示了 cJSON 的基本流程:解析字符串、获取对象成员、检查类型、获取值,最后释放内存。
总结
- JSON 是一种通用的数据格式,而 cJSON 是在 C 环境中处理这种格式的得力工具。
- 核心流程:
- 解析: 字符串 ->
cJSON_Parse()
->cJSON
对象。 - 访问/操作:
cJSON_GetObjectItem()
,cJSON_GetArrayItem()
, 检查类型,获取valuestring
/valueint
/valuedouble
。 - 创建:
cJSON_Create<Type>()
,cJSON_AddItemTo<Object/Array>()
。 - 序列化:
cJSON
对象 ->cJSON_Print()
/cJSON_PrintUnformatted()
-> 字符串。 - 内存管理:
cJSON_Delete()
用于释放cJSON
对象树,free()
(或cJSON_free()
) 用于释放cJSON_Print
返回的字符串。
- 解析: 字符串 ->
相关文章:
JSON 和 cJSON 库入门教程
第一部分:了解 JSON (JavaScript Object Notation) 什么是 JSON? JSON 是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于机器解析和生成。 JSON 基于 JavaScript 编程语言的一个子集,但它是一种独立于语言的文本格式…...
Unity 2D 行走动画示例工程手动构建教程-AI变成配额前端UI-完美游戏开发流程
🎮 Unity 2D 行走动画示例工程手动构建教程 ✅ 1. 新建 Unity 项目 打开 Unity Hub: 创建一个新项目,模板选择:2D Core项目名:WalkAnimationDemo ✅ 2. 创建文件夹结构 在 Assets/ 目录下新建以下文件夹:…...
[Java][Leetcode middle] 45. 跳跃游戏 II
这题没做出来,看的答案解析 可以理解为希望采用最少得跳槽次数跳到最高级别的公司。 下标i为公司本身的职级,每个公司可以提供本身等级nums[i]的职级提升。 每次从这些选择中选择自己能够达到最大职级的公司跳槽。 public int jump(int[] nums) {if(nu…...
leetcode 3335. 字符串转换后的长度 I
给你一个字符串 s 和一个整数 t,表示要执行的 转换 次数。每次 转换 需要根据以下规则替换字符串 s 中的每个字符: 如果字符是 z,则将其替换为字符串 "ab"。否则,将其替换为字母表中的下一个字符。例如,a 替…...
Leetcode 3542. Minimum Operations to Convert All Elements to Zero
Leetcode 3542. Minimum Operations to Convert All Elements to Zero 1. 解题思路2. 代码实现 题目链接:3542. Minimum Operations to Convert All Elements to Zero 1. 解题思路 这一题的处理方法其实还是挺好想明白的,其实就是从小到大依次处理各个…...
如何使用C51的Timer0实现定时功能
在C51单片机中,使用定时器0(Timer0)实现定时功能需要以下步骤: 1. 定时器基础知识 时钟源:C51的定时器时钟来源于晶振(如12MHz)。机器周期:1个机器周期 12个时钟周期(1…...
Day1 时间复杂度
一 概念 在 C 中,时间复杂度是衡量算法运行时间随输入规模增长的趋势的关键指标,用于评估算法的效率。它通过 大 O 表示法(Big O Notation) 描述,关注的是输入规模 n 趋近于无穷大时,算法时间增长的主导因…...
PostgreSQL 配置设置函数
PostgreSQL 配置设置函数 PostgreSQL 提供了一组配置设置函数(Configuration Settings Functions),用于查询和修改数据库服务器的运行时配置参数。这些函数为数据库管理员提供了动态管理数据库配置的能力,无需重启数据库服务。 …...
美学心得(第二百七十六集) 罗国正
美学心得(第二百七十六集) 罗国正 (2025年4月) 3275、人类将迎来真、善、美快速发展的时期,人‐机合一的天人合一(可简称为“天人机合一”)的境界已渐露头角,在优秀的人群中迅猛地…...
描述性统计工具 - AxureMost 落葵网
描述性统计工具是用于汇总和分析数据,以更好地了解数据特征的工具1。以下是一些常见的描述性统计工具简介: 描述性统计工具 Excel 基本统计函数:提供了丰富的函数用于计算描述性统计量。例如,AVERAGE 函数用于计算平均值…...
mybatis中${}和#{}的区别
先测试,再说结论 userService.selectStudentByClssIds(10000, "wzh or 11");List<StudentEntity> selectStudentByClssIds(Param("stuId") int stuId, Param("field") String field);<select id"selectStudentByClssI…...
【OpenCV】网络模型推理的简单流程分析(readNetFromONNX、setInput和forward等)
目录 1.模型读取(readNetFromONNX())1.1 初始化解析函数(parseOperatorSet())1.2 提取张量(getGraphTensors())1.3 节点处理(handleNode()) 2.数据准备(blobFromImage() …...
代码随想录算法训练营第三十九天
LeetCode题目: 115. 不同的子序列583. 两个字符串的删除操作72. 编辑距离 其他: 今日总结 往期打卡 115. 不同的子序列 跳转: 115. 不同的子序列 学习: 代码随想录公开讲解 问题: 给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数。 测试用例保…...
InternVL3: 利用AI处理文本、图像、视频、OCR和数据分析
InternVL3推动了视觉-语言理解、推理和感知的边界。 在其前身InternVL 2.5的基础上,这个新版本引入了工具使用、GUI代理操作、3D视觉和工业图像分析方面的突破性能力。 让我们来分析一下是什么让InternVL3成为游戏规则的改变者 — 以及今天你如何开始尝试使用它。 InternVL…...
力扣刷题Day 48:盛最多水的容器(283)
1.题目描述 2.思路 学习了Krahets佬的双指针思路,初始化两个边界作为容器边界,然后逐个向数组内遍历,直到左右两指针相遇。 3.代码(Python3) class Solution:def maxArea(self, height: List[int]) -> int:left,…...
基于单应性矩阵变换的图像拼接融合
单应性矩阵变换 单应性矩阵是一个 3x3 的可逆矩阵,它描述了两个平面之间的投影变换关系。在图像领域,单应性矩阵可以将一幅图像中的点映射到另一幅图像中的对应点,前提是这两幅图像是从不同视角拍摄的同一平面场景。 常见的应用场景&#x…...
《驱动开发硬核特训 · 专题篇》:深入理解 I2C 子系统
关键词:i2c_adapter、i2c_client、i2c_driver、i2c-core、platform_driver、设备树匹配、驱动模型 本文目标:通过实际代码一步步讲清楚 I2C 子系统的结构与运行机制,让你不再混淆 platform_driver 与 i2c_driver 的职责。 🧩 一、…...
Spark缓存-cache
一、RDD持久化 1.什么时候该使用持久化(缓存) 2. RDD cache & persist 缓存 3. RDD CheckPoint 检查点 4. cache & persist & checkpoint 的特点和区别 特点 区别 二、cache & persist 的持久化级别及策略选择 Spark的几种持久化…...
tails os系统详解
一、起源与发展背景 1. 项目初衷与历史 创立时间:Tails 项目始于 2004 年,最初名为 “Anonymous Live CD”,2009 年正式更名为 “Tails”(The Amnesic Incognito Live System,“健忘的匿名实时系统”)。核…...
[洛谷刷题9]
P2376 [USACO09OCT] Allowance G(贪心) https://www.luogu.com.cn/problem/P2376 题目描述 作为创造产奶纪录的回报,Farmer John 决定开始每个星期给Bessie 一点零花钱。 FJ 有一些硬币,一共有 N ( 1 ≤ N ≤ 20 ) N (1 \le …...
数据挖掘入门-二手车交易价格预测
一、二手车交易价格预测 1-1 项目背景 随着二手车市场的快速发展,二手车交易价格的预测成为了一个热门研究领域。精准的价格预测不仅能帮助买卖双方做出更明智的决策,还能促进市场的透明度和公平性。对于买家来说,了解合理的市场价格可以避免…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】金融风控分析案例-10.4 模型部署与定期评估
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 10.4 模型部署与定期评估10.4.1 模型部署架构设计1.1 模型存储方案1.2 实时预测接口 10.4.2 定期评估体系构建2.1 评估指标体系2.2 自动化评估流程2.3 模型衰退预警 10.4.3 …...
构建可信数据空间需要突破技术、规则和生态三大关键
构建可信数据空间需要突破技术、规则和生态三大关键:技术上要解决"可用不可见"的隐私计算难题,规则上要建立动态确权和跨境流动的治理框架,生态上要形成多方协同的标准体系。他强调,只有实现技术可控、规则可信、生态协…...
阳光学院【2020下】计算机网络原理-A卷-试卷-期末考试试卷
一、单选题(共25分,每空1分) 1.ICMP协议工作在TCP/IP参考模型的 ( ) A.主机-网络 B.网络互联层 C.传输层 D.应用层 2.下列关于交换技术的说法中,错误的是 ( ) A.电路交换适用于突发式通信 B.报文交换不能满足实时通信 C.报文…...
python: union()函数用法
在 Python 中,union() 是集合(set)类型的内置方法,用于返回两个或多个集合的并集(即所有元素的合集,自动去重)。以下是它的用法详解: 1. 基本语法 python 复制 下载 set.union(*…...
docker部署WeDataSphere开源大数据平台
GitHub:https://github.com/WeBankFinTech/WeDataSphere **WDS容器化版本是由Docker构建的一个能够让用户在半小时内完成所有组件安装部署并使用的镜像包。**无需再去部署Hadoop等基础组件,也不需要部署WDS的各功能组件,即可让您快速体验 WD…...
【计算机视觉】OpenCV项目实战:基于face_recognition库的实时人脸识别系统深度解析
基于face_recognition库的实时人脸识别系统深度解析 1. 项目概述2. 技术原理与算法设计2.1 人脸检测模块2.2 特征编码2.3 相似度计算 3. 实战部署指南3.1 环境配置3.2 数据准备3.3 实时识别流程 4. 常见问题与解决方案4.1 dlib安装失败4.2 人脸检测性能差4.3 误识别率高 5. 关键…...
uni-app学习笔记五-vue3响应式基础
一.使用ref定义响应式变量 在组合式 API 中,推荐使用 ref() 函数来声明响应式状态,ref() 接收参数,并将其包裹在一个带有 .value 属性的 ref 对象中返回 示例代码: <template> <view>{{ num1 }}</view><vi…...
阿克曼-幻宇机器人系列教程2- 机器人交互实践(Topic)
在上一篇文章中,我们介绍了两种登录机器人的方式,接下来我们介绍登录机器人之后,我们如何通过topic操作命令实现与机器人的交互。 1. 启动 & 获取topic 在一个终端登录树莓派后,执行下列命令运行机器人 roslaunch huanyu_r…...
Windows系统事件查看器管理单元不可用
报错:Windows系统事件查看器管理单元不可用 现象原因:为误触关闭管理单元或者该模块卡死 解决办法:重启Windows server服务,若不行,则重启服务器即可...
milvus+flask山寨《从零构建向量数据库》第7章case2
继续流水账完这本书,这个案例是打造文字形式的个人知识库雏形。 create_context_db: # Milvus Setup Arguments COLLECTION_NAME text_content_search DIMENSION 2048 MILVUS_HOST "localhost" MILVUS_PORT "19530"# Inference Arguments…...
前端如何应对精确数字运算?用BigNumber.js解决JavaScript原生Number类型在处理大数或高精度计算时的局限性
目录 前端如何应对精确数字运算?用BigNumber.js解决JavaScript原生Number类型在处理大数或高精度计算时的局限性 一、BigNumber.js介绍 1、什么是 BigNumber.js? 2、作用领域 3、核心特性 二、安装配置与基础用法 1、引入 BigNumber.js 2、配置 …...
多目应用:三目相机在汽车智能驾驶领域的应用与技术创新
随着汽车智能驾驶技术不断完善,智能汽车也不断加速向全民普惠迈进,其中智驾“眼睛”三目视觉方案凭借低成本、高精度、强适配性成为众多汽车品牌关注的焦点。三目相机在汽车智能驾驶领域的创新应用,主要依托其多视角覆盖、高动态范围…...
webpack重构优化
好的,以下是一个关于如何通过重构 Webpack 构建策略来优化性能的示例。这个过程包括分析现有构建策略的问题、优化策略的制定以及具体的代码实现。 --- ### 项目背景 在参与公司的性能专项优化过程中,我发现现有的 Webpack 构建策略存在一些问题&#…...
MySQL 8.0 OCP(1Z0-908)英文题库(31-40)
目录 第31题题目分析正确答案 第32题题目分析正确答案 第33题题目分析正确答案: 第34题题目解析正确答案 第35题题目分析正确答案 第36题题目分析正确答案 第37题题目分析正确答案 第38题题目分析正确答案 第39题题目分析正确答案 第40题题目分析正确答案 第31题 Y…...
aardio - 虚表 —— vlistEx.listbar2 多层菜单演示
在 近我者赤 修改版的基础上,做了些许优化。 请升级到最新版本。 import win.ui; import godking.vlistEx.listbar2; import fonts.fontAwesome; /*DSG{{*/ mainForm win.form(text"多层折叠菜单";right1233;bottom713) mainForm.add({ custom{cls"…...
22.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--增加公共代码
在拆分服务之前,我们需要先提取一些公共代码。本篇将重点新增日志记录、异常处理以及Redis的通用代码。这些组件将被整合到一个共享类库中,便于在微服务架构中高效复用。 Tip:在后续的教程中我们会穿插多篇提取公共代码的文章,帮助…...
EasyOps®5月热力焕新:三大核心模块重构效能边界
在应用系统管理中,我们将管理对象从「服务实例」优化为「部署实例」,这一改变旨在提升管理效率与数据展示清晰度。 此前,系统以 “IP Port” 组合定义服务实例。当同一 IP 下启用多个进程或端口时,会产生多个服务实例。比如一台…...
基于深度学习的工业OCR数字识别系统架构解析
一、项目场景 春晖数字识别视觉检测系统专注于工业自动化生产监控、设备运行数据记录等关键领域。系统通过高精度OCR算法,能够实时识别设备上显示的关键数据(如温度、压力、计数等),并定时存储至Excel文件中。这些数据对于生产过…...
R语言绘图 | 渐变火山图
客户要求绘制类似文章中的这种颜色渐变火山图,感觉挺好看的。网上找了一圈,发现有别人已经实现的类似代码,拿来修改后即可使用,这里做下记录,以便后期查找。 简单实现 library(tidyverse)library(ggrepel)library(ggf…...
Go语言——docker-compose部署etcd以及go使用其服务注册
一、docker-compsoe.yml文件如下 version: "3.5"services:etcd:hostname: etcdimage: bitnami/etcd:latestdeploy:replicas: 1restart_policy:condition: on-failureprivileged: truevolumes:# 持久化 etcd 数据到宿主机- "/app/apisix/etcd/data:/bitnami/etc…...
Tomcat的调优
目录 一. JVM 1.1 JVM的组成 1.2 运行时数据区域的组成 二. 垃圾回收 2.1 如何确认垃圾 1. 引用计数法 2. 根搜索算法 2.2 垃圾回收基本算法 1. 标记-清除算法(Mark-Sweep) 2. 标记-压缩算法(Mark-Compact) 3. 复制算法…...
Tomcat和Nginx的主要区别
1、功能定位 Nginx:核心是高并发HTTP服务器和反向代理服务器,擅长处理静态资源(如HTML、图片)和负载均衡。Tomcat:是Java应用服务器,主要用于运行动态内容(如JSP、Servlet)…...
Python训练营打卡——DAY24(2025.5.13)
目录 一、元组 1. 通俗解释 2. 元组的特点 3. 元组的创建 4. 元组的常见用法 二、可迭代对象 1. 定义 2. 示例 3. 通俗解释 三、OS 模块 1. 通俗解释 2. 目录树 四、作业 1. 准备工作 2. 实战代码示例 3. 重要概念解析 一、元组 是什么:一种…...
【TDengine源码阅读】DLL_EXPORT
2025年5月13日,周二清晨 #ifdef WINDOWS #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT #endif为啥Linux和MacOS平台时宏为空,难道Linux和mac不用定义导出函数吗? 这段代码是一个跨平台的宏定义,用于处理不…...
电子科技浪潮下的华秋电子:慕尼黑上海电子展精彩回顾
为期3天的2025慕尼黑上海电子展(electronica China 2025)于17日在上海新国际博览中心落下帷幕。 展会那规模,真不是吹的!本届展会汇聚了1,794家国内外行业知名品牌企业的展商来 “摆摊”,展览面积大得像个超级大迷宫&…...
TDengine编译成功后的bin目录下的文件的作用
2025年5月13日,周二清晨 以下是TDengine工具集中各工具的功能说明: 核心工具 taosd • TDengine的核心服务进程,负责数据存储、查询和集群管理。 taos • 命令行客户端工具,用于连接TDengine服务器并执行SQL操作。 taosBenchma…...
spark sql基本操作
Spark SQL 是 Apache Spark 的一个模块,用于处理结构化数据。它允许用户使用标准的 SQL 语法来查询数据,并且可以无缝地与 Spark 的其他功能(如 DataFrame、Dataset 和 RDD)结合使用。以下是 Spark SQL 的基本使用方法和一些常见操…...
采购流程规范化如何实现?日事清流程自动化助力需求、采购、财务高效协作
采购审批流程全靠人推进,内耗严重,效率低下? 花重金上了OA,结果功能有局限、不灵活? 问题出在哪里?是我们的要求太多、太苛刻吗?NO! 流程名称: 采购审批管理 流程功能…...
影刀RPA开发-CSS选择器介绍
影刀RPA网页自动化开发,很多时候需要我们查看页面源码,查找相关的元素属性,这就需要我们有必要了解CSS选择器。本文做了些简单的介绍。希望对大家有帮助! 1. CSS选择器概述 1.1 定义与作用 CSS选择器是CSS(层叠样式…...