news 2026/10/6 19:31:56

RAG与Agent实战:JSON基础使用与常见排查指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RAG与Agent实战:JSON基础使用与常见排查指南

第二周 RAG与Agent实战06:Json的基础使用

我最早做企业知识库RAG项目时,文档切分、向量化、召回排序全都调通了,结果卡在最不起眼的一环——把切分好的文本块和元数据写进知识库的时候,解析器一碰到某些字段就报错。排查到最后发现,不是解析器的问题,是我自己手工拼接的JSON漏了转义。

大概从那时候起我明白了一个道理:RAG和Agent项目里,一半以上的bug不是模型的问题,不是向量库的问题,而是JSON的问题。模型输出要JSON、工具调用参数要JSON、知识库文档元数据要JSON、API请求响应还是JSON。JSON在AI应用里扮演的角色,比大多数人想象中重要得多。

这篇是RAG与Agent实战系列第二周的第六讲,目的很直接:把JSON这个基础件彻底打牢。我会结合RAG知识库和Agent工具调用这两个实际场景,讲清楚JSON的语法细节、结构设计思路、常见坑和排查方法。适合正在做RAG或Agent开发、但经常被JSON相关bug折磨的朋友,也适合刚接触AI应用开发、想把基础补扎实的初学者。

1. 为什么RAG和Agent实战绕不开JSON

1.1 JSON是LLM应用里的统一数据交换语言

先想一个问题:你写一个RAG系统,里面有文档解析模块、向量化模块、检索模块、生成模块,这些模块之间靠什么传递数据?再想另一个问题:你调用一个大模型API,告诉它"帮我查一下天气然后订个机票",它怎么把工具调用的意图和参数表达给你?

两个问题的答案都是JSON。

JSON在AI应用里承担的角色,相当于整个系统的"通用语言"。后端用它传数据,大模型用它表达意图,前端用它渲染界面。说白了,不管你的项目用什么编程语言、什么向量数据库、什么模型供应商,只要涉及结构化数据的传输和存储,几乎绕不开JSON。这不是谁规定的行业标准,而是生态自然选择的结果——它比XML轻量,比CSV能表达嵌套关系,比YAML少踩缩进的坑,而且几乎所有编程语言都有成熟的JSON解析库。

做RAG项目时,你需要把非结构化文档切成块,每个块要带上来源、标题、页码、章节层级这些元信息,这种"文本内容+结构属性"的形态用JSON表达最自然。做Agent项目时,模型需要按照预定义的格式输出工具调用参数,JSON是最普遍的选择。

1.2 没有JSON意识的RAG/Agent项目会踩哪些坑

很多人觉得JSON简单,不就是一个花括号加冒号吗?确实,读一个写得很规范的JSON文件没有任何难度。但到了RAG和Agent的实际项目里,问题就复杂了:

  • 模型输出的JSON不一定合法,可能多了个逗号,可能字符串没有闭合引号,可能嵌套层数不对。
  • RAG知识库导入时,元数据字段类型不一致——同一批文档里有的id是数字,有的是字符串,导入向量库时直接报错。
  • Agent工具调用时,模型把JSON Schema规定的数字参数传成了带引号的字符串,工具执行层拿到之后傻眼了。
  • 多轮对话里状态管理依赖JSON的deep merge,但嵌套字段的合并策略没定清楚,越改越乱。

这些坑的共同点是:表面上看是"程序报错"或者"模型不听话",根子上都是JSON的使用方式出了问题。如果对JSON的数据结构、序列化规则、Schema约束有足够深的理解,大部分问题在设计阶段就能规避。

2. 语法精讲:只讲RAG与Agent场景里最容易翻车的JSON细节

2.1 数据类型、嵌套结构与数组遍历

先快速过一遍规则。JSON有六种数据类型:对象、数组、字符串、数字、布尔值、null。对象用花括号,数组用方括号,字符串必须用双引号,数字不带引号,true/false是小写,null也是小写。就这么点规则,但实际项目里翻车的恰恰是这些"简单规则"的边界情况。

数字是JSON里最容易踩坑的类型之一。大的整数ID,比如雪花算法生成的ID,在JavaScript里超过Number.MAX_SAFE_INTEGER就会丢精度;在Python里虽然int没有上限,但解析成float就会变成科学计数法。所以外部ID字段我的习惯是一律当字符串处理,强制加引号,别图省事。

嵌套结构的访问是另一个高频问题。RAG文档元数据经常是三层四层的嵌套,比如按一级分类、二级分类、标签组来组织。这时候用点号取值的方式很容易因为中间某层是null而报错。我的处理方式是用一个安全取值函数,不要每处都自己写if判断:

def safe_get(data, path, default=None): """从嵌套JSON中安全取值,路径用点号分隔。""" if data is None: return default keys = path.split(".") value = data try: for key in keys: value = value[key] return value except (KeyError, TypeError, IndexError): return default

这个函数写出来的价值不在于复杂,而在于统一。项目中所有从嵌套JSON里取值的逻辑都走这一个入口,就不会出现"这个地方忘了判空、那个地方类型写错"的散装bug。

数组遍历相对简单,但要注意RAG场景里一个常见需求:把文档块数组批量转换成向量化任务的输入列表。这里容易犯的错误是只遍历一层就以为做完了,实际上很多JSON数组里嵌套着对象,对象里又有数组,需要递归处理。

2.2 字符串转义、Unicode与空值处理

字符串转义是另一个翻车重灾区。JSON字符串里如果包含双引号、反斜杠、换行符,必须进行转义。最典型的场景是:你用Python把一篇包含代码示例的Markdown文档转成JSON字符串,文档里有大量双引号和反斜杠,如果直接json.dumps,得到的字符串里这些字符都被转义成了\"和\\,这是正确的。

但问题往往出在手工拼JSON的时候。比如有人喜欢用f-string拼JSON:

metadata = '{"title": "' + title + '", "content": "' + content + '"}'

一旦title或content里包含双引号、换行,拼出来的字符串一定非法。正确做法是永远用语言自带的序列化方法生成JSON,不要手工拼接:

import json metadata = json.dumps({ "title": title, "content": content }, ensure_ascii=False)

注意ensure_ascii=False这参数,很多刚入门的人容易忽略。默认情况下json.dumps会把所有非ASCII字符转成\uXXXX形式,中文全变成转义序列。这个行为本身是合法的JSON,但问题在于:可读性极差、日志里看着费劲、某些下游解析器处理不当还会把Unicode转义再转一次造成乱码。设置ensure_ascii=False输出原始字符,配合UTF-8编码,能避免绝大部分乱码问题。

空值处理也值得单独说。JSON的null在Python里是None,在Java里是null,在JavaScript里是null。看起来对应关系明确,但业务逻辑上没有约定好"空字符串、null、缺失字段"三者之间的区别时,问题就来了。

我做RAG知识库元数据设计的时候,会明确约定:字段不存在用缺省(直接把key省掉),值为空用空字符串,确实无效值才用null。这个约定看着简单,但对下游检索的过滤逻辑影响很大——比如你想筛选出所有标题非空的文档,用NullValue还是空字符串判断,写出来的查询条件完全不一样。实际项目中我见过最头疼的情况是同一个字段三种状态混着出现,最后只能写一堆兼容逻辑擦屁股。所以建数据结构的时候就把这个约定写清楚,省得后面返工。

3. RAG实战:知识库文档的JSON设计比解析更重要

3.1 从文档到JSONL:一个批量导入的知识库元数据设计案例

RAG知识库的典型工作流程里,绝大多数人会重点关注文档切分和向量化,却很少一开始就认真设计元数据的JSON结构。这导致项目后期做过滤、做权限控制、做增量更新的时候,才发现元数据字段要么不够用,要么字段类型混乱。

我以一个团队知识库为例,说明我是怎么设计文档JSON结构的。团队知识库里有产品说明书、API文档、内部规范、会议纪要四类文档,每类文档的元数据侧重点不同,但为了让写入向量库时字段统一,我会画一个基础字段模板:

{ "doc_id": "doc_20240615_001", "title": "订单服务API文档", "doc_type": "api_docs", "owner": "payment_team", "permission": "internal", "version": "2.3.1", "tags": ["order", "api", "payment"], "chunk_index": 0, "chunk_count": 12 }

doc_id必须全库唯一且稳定,这是增量更新的基础——同一个文档被重新切分后,旧的chunk要用doc_id定位删除,再写入新的。chunk_index和chunk_count用来记录当前块在完整文档中的位置,做上下文拼接时特别有用。permission字段可以做权限过滤,确保不同团队只能检索到自己的文档。

有了这个模板还不够,还要把它落实到批量导入流程里。我常用的做法是把所有文档的元数据写成JSONL文件,每一行是一个完整的chunk对象,然后用Python逐行读取导入知识库。

为什么用JSONL而不是一个巨大的JSON数组?因为JSONL每一行独立,可以边读边处理,不用把整个文件加载到内存;某一行格式坏了,跳过它不影响其他行;遇到大批量导入还能用并发处理,一个线程读一行导一行。

这里有个容易被忽略的点:JSONL的每一行必须是一个完整的JSON对象,不能有额外的逗号或括号。手动编辑的话容易在行尾漏掉换行,或者在某一行末尾多加一个逗号。我的建议是JSONL文件不要手工编辑,要由脚本从原始文档自动生成,通过一个中间数据结构批量转换:

import json import pathlib def build_chunks_from_docs(doc_dir): """从文档目录批量生成JSONL。""" output_path = pathlib.Path("chunks.jsonl") with output_path.open("w", encoding="utf-8") as f: for doc_path in doc_dir.glob("*.md"): doc_id = f"doc_{doc_path.stem}" title = doc_path.stem text = doc_path.read_text(encoding="utf-8") chunks = split_text_to_chunks(text, max_length=500, overlap=50) for i, chunk in enumerate(chunks): chunk_obj = { "doc_id": doc_id, "title": title, "chunk_index": i, "chunk_count": len(chunks), "content": chunk } f.write(json.dumps(chunk_obj, ensure_ascii=False) + "\n")

这个脚本把原始文档切块后自动转成JSONL,中间不需要手工介入,格式一致性有保证。等落实到这一步,你才会体会到"元数据设计对了,后面流程多省心"的感觉。

3.2 知识库的图片、结构化数据与纯文本如何共存

热搜词里有个问题很有意思:"rag知识库能存储图片嘛?"这背后反映了一个普遍困惑:RAG知识库到底能装什么类型的数据?

直接给结论:大多数主流向量知识库的存储对象是"文本切片+向量+元数据",图片本身不能直接进向量库。但图片可以通过两种方式间接接入RAG:一种是给图片生成描述文本,把"图片路径+描述文本+视觉向量"存进去;另一种是RAG+多模态模型,检索时把图片路径作为上下文传给视觉模型。两种方式里JSON都是粘合剂——图片路径、描述文本、标签、归属目录这些都打包在JSON元数据里。

纯文本、结构化数据、图片这三者在知识库里的共存方式,本质上就是元数据JSON的设计问题。我见过一个文档知识库把API的OpenAPI Spec(JSON格式)、产品介绍Markdown、产品截图三种内容放在同一个collection里,做法是给每个chunk打上data_type字段,检索的时候根据查询意图只召回对应类型的数据。这个思路和做权限过滤一脉相承,都是靠元数据来控制和路由。

很多人纠结"知识图谱、RAG知识库、结构化知识库"三者的区别和选择,我的理解很直接:RAG知识库擅长非结构化文本的语义检索,结构化知识库擅长精确查询和聚合统计,知识图谱擅长多跳关系和推理。它们不是二选一的对立关系,实际项目里经常是RAG为主、结构化为辅、图谱做复杂关联。而JSON在这个混合架构里充当的是数据交换的统一格式——非结构化文本的切块、结构化查询的结果、图谱遍历的路径,最终都能映射成JSON对象。所以你把JSON啃扎实,等于给这些架构打了一个通用的地基。

4. Agent实战:工具调用中的JSON参数约束与安全解析

4.1 Function Calling的Schema设计:把约束写在JSON之前

Agent应用里JSON最核心的战场是工具调用。现在主流模型都支持Function Calling,模型根据用户请求决定"要不要调用工具、调用哪个工具、传什么参数",然后把调用的结果以JSON形式返回。

这个机制本身不复杂,但有一个很容易被忽视的问题:模型返回的工具调用参数,是模型"生成"出来的,不是你预先定义的。模型可能会把字符串传给整数参数,可能会漏掉必填字段,甚至可能在没有调用必要的时候强行调用工具。所以不能只靠模型自觉,你得在设计阶段就用JSON Schema把约束立起来。

举个例子,假设我在做一个带工具调用的Agent,其中一个工具是查询订单状态:

{ "type": "function", "function": { "name": "query_order_status", "description": "根据订单号查询订单当前状态", "parameters": { "type": "object", "properties": { "order_id": { "type": "string", "pattern": "^ORD-[0-9]{6}$" } }, "required": ["order_id"], "additionalProperties": false } } }

这段Schema看似简单,实际作用很大。它告诉模型只有order_id一个参数、必须以ORD-加六位数字的格式出现、其他多余参数不允许。我在项目里调试过对比实验,模型在收到这种严格Schema时的合规输出率,明显高于那种只写"参数随意"的Schema。

设计Schema时有几个实战经验可以分享:

  • description写详细一点,把参数的取值范围、格式例子写清楚。模型是靠description理解参数的,不是靠参数名猜的。比如order_id字段的description我会写"订单号,格式为ORD-后跟六位数字,例如ORD-123456"。
  • required字段宁可多写不能少写。如果有工具参数在下游逻辑里是必用的,务必列进required,否则模型漏传了,代码里还得做一大堆兜底。
  • additionalProperties: false这个约束非常有用。它禁止模型添加你没定义的额外参数。模型有时候会自作主张往参数里加东加西,比如你以为它只传order_id,结果它顺手塞了一个user_name进去。additionalProperties一关,这种问题直接杜绝。

做完Schema限制,工具执行层的参数校验也要跟上去。我的习惯是工具执行入口再做一次基于Schema的校验,防止模型生成的JSON混进类型不对的字段。Python里可以用jsonschema库,定义好Schema后直接调用validate方法:

import jsonschema def execute_tool(tool_name, params, tool_schema): try: jsonschema.validate(params, tool_schema) except jsonschema.ValidationError as e: return {"success": False, "error": f"参数校验失败: {e.message}"} # 校验通过后执行实际工具逻辑 return run_tool(tool_name, params)

这个过程Double Check不要嫌麻烦。模型侧有Schema约束,执行侧有独立校验,两边都做了才能确保工具调用安全可靠。

4.2 模型输出JSON的可靠性问题与容错处理

Agent场景里另一个绕不开的问题是:模型输出的JSON不一定可靠。即使你给了严格的Schema描述,模型偶尔还是会输出残缺的JSON。实际项目里主要遇到的不合法形式有:多余的尾随逗号、字符串该转义没转义、JSON被markdown的代码块包住导致前后有```符号、整段输出里混入了模型自己的解说文字。

针对这些情况,我总结了一套容错解析流程:

第一步做清理:先把模型输出外包的markdown代码块剝掉。正则匹配json和之间的联系部分。

第二步尝试标准解析:json.loads直接解析。

第三步走增强解析:如果标准解析失败,用第三方容错解析库尝试修复。Python里我用json5或者demoji这类(实际项目中json5库能容忍尾随逗号和单引号)。

第四步如果还是失败,就丢弃这次输出,让模型重新生成一次。对于流程编排而言,"返回重试"在Agent场景非常常见,关键是纠错逻辑要做对。

我的容错解析函数大致长这样:

import re import json def parse_model_json(raw_output): """解析模型输出,尽量提取出有效的JSON对象。""" if raw_output is None: raise ValueError("模型输出为空") text = raw_output.strip() # 去掉markdown代码块围栏 fence_match = re.search(r"```(?:json)?\s*(.*?)\s*```", text, re.DOTALL) if fence_match: text = fence_match.group(1).strip() # 提取第一个JSON对象或数组 try: return json.loads(text) except json.JSONDecodeError: pass # 找到最外层花括号或方括号的起止位置 start_idx = len(text) for ch in "{[": idx = text.find(ch) if idx != -1 and idx < start_idx: start_idx = idx end_idx = -1 for i in range(start_idx + 1, len(text)): if text[i] in "}]": end_idx = i if start_idx == len(text) or end_idx == -1: raise ValueError("无法从模型输出中定位JSON") candidate = text[start_idx:end_idx + 1] return json.loads(candidate)

这个函数的基本思路是先清理外层噪声,再定位JSON主体,保证即使模型输出里带了废话也能抢救回来一部分。但有一个原则要记住:容错解析解决的是"格式不规范"的问题,不是"内容错误"的问题。模型输出的JSON字段值本身对不对,还是要通过业务逻辑验证。

Agent多轮对话里还会遇到一个高频问题:状态合并。每轮对话结束时Agent返回的状态快照要合并到全局状态里,用json.merge之类的深合并逻辑。这里注意嵌套字段的合并策略必须事先定好:新值覆盖旧值、数组是整体替换还是按元素合并?我的习惯是默认整体替换,除非业务上确实需要按key合并,否则不做递归merge,因为递归merge的边界情况远比你想象的多,一旦处理不好会产生脏数据。

5. 错误排查与调试工具:被JSON逼疯之后的拯救方案

5.1 高频报错及定位思路

JSON相关的报错信息很统一,翻来覆去就是那几个:Expecting value、Expecting property name enclosed in double quotes、Extra data、Expecting ',' delimiter。虽然报错信息短,但每条背后都有不同的原因。我整理一个高频问题对照表:

报错信息常见原因定位思路
Expecting value: line 1 column 1字符串为空,或者开头不是合法JSON字符先打印原始字符串看内容,确认是否为空、是否有BOM头
Expecting property name enclosed in double quotes用了单引号,或者key没有加引号检查是否是Python字典的str形式被误当成JSON
Extra data: line X column Y一个字符串里包含多个JSON对象,或者末尾多了字符确认是不是JSONL混淆成了JSON,或者有乱码尾随
Expecting ',' delimiter对象里两个字段之间少了逗号,或字符串里的引号没转义找到报错行号,看上一个字段的值是否嵌套了没转义的引号
string indices must be integers把字符串当成对象用下标访问了排查路径是否写错,比如data.content写成data["content"]还有错位

定位思路里我想特别强调一件事:遇到JSON解析报错,不要只盯着报错那一段看,要把整个字符串完整打印出来再观察。很多时候你拿到的是被截断的输出,报错位置在截断点附近,看起来像JSON语法错误,实际是数据被截断了。

5.2 好用的检查与转换工具链

日常开发里我主要用这几件工具处理JSON:

命令行场景用jq。检查一个JSON文件有没有问题,jq会自动做语法校验,出错直接指出行号。格式化、字段提取、数组遍历都特别顺手。比如想看一眼knowledge_base.jsonl里所有doc_type字段的分布:

jq -r '.doc_type' chunks.jsonl | sort | uniq -c

如果只是平时想快速验证一段JSON是否合法,在线工具也可以,比如json.cn和bejson这类,但有两个注意点:涉及隐私或商业数据的内容别贴在线工具;在线工具只适合单次验证,批量校验还是本地脚本靠谱。

Python场景里除了标准库json,我还会用ujson(性能好,解析速度快)和orjson(序列化快,支持datetime类型)。在加载大批量JSONL文件时,ujson的速度优势还是很明显的。

还有一类工具容易被忽略:JSON转JSON Schema的工具。虽然它生成的Schema不一定完全符合你的约束需求,但可以作为初始版本,再手工调整。比起从零手写,省了不少时间。

说到json查询函数,之前有朋友问我在代码里怎么快速查JSON里的某个字段是否存在、值是多少。如果项目里频繁用到,最推荐的是把前面说的safe_get函数封装成通用工具放到公共包里,所有项目共用。配置解析合法性校验、接口返回数据适配、文档元数据提取,都能复用。

6. 第二周六天该掌握的JSON能力清单

以"第二周第六天"这个时间节点来看,学完这篇之后你应该具备的能力,我列了一个清单,你可以对照自测:

  • 能够不看文档手写一个包含对象、数组、字符串、数字、布尔、null的JSON示例,并解释六种数据类型的边界规则。
  • 知道JSON和JSONL的区别,能在RAG项目里正确设计JSONL格式的文档切片文件。
  • 遇到JSON解析报错时,能根据报错信息快速判断是语法错误、转义错误还是截断问题。
  • 会使用Python的json.dumps和json.loads处理嵌套结构,记住ensure_ascii=False的用途。
  • 能阅读并编写基本的JSON Schema,给Agent工具定义参数约束。
  • 知道模型输出的JSON为什么可能需要容错解析,并能实现一个清理和提取逻辑。
  • 给知识库设计元数据JSON时,能考虑到唯一ID稳定、权限字段、文档类型字段这些容易被忽视但很重要的属性。

如果你对照之后发现哪一项还不牢靠,我的建议是:翻到对应章节重新看一遍,然后自己动手改一段真实的JSON数据跑一遍。光看不练的话,看十遍不如手写一遍。

7. 一个值得花半小时做的综合练习

按照实战系列的习惯,每篇最后我都会留一个综合练习。这次的练习不涉及复杂的代码库,只需要你手头有任何一个真实的业务场景数据就行。

假设你正在做一个RAG知识库,需要把一批产品文档导入向量数据库。请你动手做三件事:

第一,设计一套元数据字段模板,要求包含文档ID、标题、类型、归属团队、权限级别、标签、块序号、总块数这八个字段,并写明每个字段的类型。拿你手头任意一篇文档切出至少三个块,用代码生成一个JSONL文件。

第二,把这个JSONL文件故意改坏一行(比如删掉一个逗号或引号),写一个小脚本逐行读取并跳过坏行,同时记录坏行的行号和错误原因。

第三,为你的知识库定义一个搜索过滤场景,比如"只看权限为internal的文档",然后说明你在检索维度上会怎么利用元数据实现这个过滤,是精确匹配还是向量召回后过滤。

这个练习做完,你对JSON在RAG里的用法会形成比看十篇文章更深的肌肉记忆。形式不重要,重要的是亲手过一遍。

我个人在实际项目里的体会是,JSON技术点本身确实简单,难的是你始终把它当作系统设计的一等公民来对待,而不是"一个需要处理的数据格式"。当你开始认真设计JSON结构、定义约束Schema、规划容错机制的时候,RAG和Agent项目的稳定性会明显上一个台阶。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 19:25:47

基于Spring Boot的养老院信息管理系统设计与实现

养老机构的管理一直是个“看着简单、做起来琐碎”的活儿。床位有没有空余、哪位老人该体检了、家属这个月费用缴没缴、护工的排班有没有冲突——这些信息如果还停留在纸质台账或者Excel表里&#xff0c;一旦数据量上来&#xff0c;光是对账和查漏就能耗掉管理员大半天的精力。我…

作者头像 李华
网站建设 2026/10/6 19:24:02

FDA波束形成原理与MATLAB实战:频率分集阵列距离-角度耦合建模

简介&#xff1a;本资源是一套完整的FDA波束形成MATLAB仿真程序包&#xff0c;面向雷达、无线通信及信号处理方向的研究生、工程师与科研人员&#xff0c;聚焦频率多样性算法在多载频系统中的波束合成、干扰抑制与目标定位实践。程序包共15个文件&#xff0c;含9个核心.m脚本&a…

作者头像 李华
网站建设 2026/10/6 19:20:24

OpenShell:面向命令行的会话管理与持久化工具实战指南

1. 从一个终端窗口说起&#xff1a;OpenShell 到底在解决什么问题如果你日常跟 Linux 服务器、嵌入式设备或者各种命令行工具打交道&#xff0c;大概率经历过这样的场景&#xff1a;同时开着五六个终端标签页&#xff0c;每个标签页里跑着不同的会话&#xff0c;时间一长自己都…

作者头像 李华
网站建设 2026/10/6 19:19:54

OpenShell 终端复用实战:会话保持、窗口分割与工作流优化

1. 从一个终端窗口说起&#xff1a;OpenShell 到底在解决什么问题如果你日常跟 Linux 服务器、容器或者嵌入式设备打交道&#xff0c;大概率经历过这样的场景&#xff1a;打开一个终端&#xff0c;敲几条命令&#xff0c;然后需要同时盯着日志输出、监控资源占用、再开一个窗口…

作者头像 李华
网站建设 2026/10/6 19:18:17

Redis分布式锁在秒杀场景下的实现与避坑指南

简介&#xff1a;这份资源围绕高并发场景下的抢单秒杀需求&#xff0c;给出基于Redis分布式锁的完整实现方案&#xff0c;面向具备SpringBoot与Redis基础的Java后端开发者&#xff0c;以及需要应对超卖、重复抢单等并发问题的电商系统学习者。压缩包共13个文件&#xff0c;约59…

作者头像 李华
网站建设 2026/10/6 19:16:14

HarmonyOS ArkUI焦点事件实战:TV端遥控器导航从原理到踩坑

做TV端应用的人都知道&#xff0c;遥控器方向键按下去&#xff0c;焦点能不能落到用户预期的那块组件上&#xff0c;基本决定了这个应用好不好用。我在HarmonyOS NEXT 5.0.0(12)也就是API 12的环境上&#xff0c;用ArkUI重构了一个视频应用的遥控器导航模块&#xff0c;整个过程…

作者头像 李华