把 json-render 接进生产,我踩过的坑:安全边界、流式渲染与组件白名单
把 json-render 接进生产我踩过的坑安全边界、流式渲染与组件白名单【免费下载链接】json-renderThe Generative UI framework项目地址: https://gitcode.com/GitHub_Trending/js/json-renderVercel Labs 开源的 json-render 在过去一段时间里几乎刷屏了整个前端圈上线几天 GitHub Star 数就从 7500 冲到 1 万核心卖点一句话就能讲完——让 AI 在开发者定义的护栏里生成界面。它不再让大模型直接吐 HTML/JSX 这种不可控的代码而是输出一份 JSON spec由你自己的渲染器把 spec 变成 UI。这个思路确实漂亮但demo 很炫和能上线之间隔着一整条生产链路。我把它接进真实业务后先后踩过三个大坑安全边界到底划在哪、流式渲染怎么做才不崩、组件白名单怎么设计 AI 才不会乱来。这篇文章不是产品吹捧是基于仓库源码的工程复盘希望能帮后来者少走弯路。接入前的高频假设与现实的落差接触 json-render 之前大多数人包括我会有三组默认假设假设一安全是框架自动保证的。实际上框架只保证约束 AI 的输出结构真正的安全边界要靠你定义 catalog 时自己划出来假设二流式渲染就是把流接进来就行。实际上 LLM 输出是逐 token 到达的spec 是增量 patch 拼接出来的任何一个半行 JSON 处理不当整棵树就会渲染出残次品假设三白名单组件越多越好。实际上 AI 的自由发挥和你的维护成本成正比白名单设计得越克制输出越稳定。这三组落差正好对应下面三个坑。坑一安全边界——真正的护栏是组件 动作 数据绑定三张白名单json-render 的第一条设计原则写在 README.md 里AI can only use components in your catalogAI 只能用你 catalog 里的组件。这句话很容易被误读为框架替我挡住了所有风险。真相是框架只提供了一个机制边界划在哪里完全取决于你。在核心包 schema.ts 里defineCatalog要求你同时声明两件事AI 能用的组件components和 AI 能触发的动作actions。AI 生成的 spec 里出现的每一个type、每一个action都被限制在这两个字典里。渲染器侧的 registry.tsx 则要求你为每个组件名提供你自己写的实现——这意味着 AI 永远不可能凭空执行任意函数它只能组合你提供的积木。这是整个安全模型的根基与其让 LLM 输出可执行代码不如让它输出数据 受控引用执行路径完全掌握在应用手里。我踩的第一个坑就是早期想让 AI 直接操作某些内部方法最后被硬拉回白名单模型——这其实是对的只是当时没想明白。动作actions是第二张安全面也是最容易漏的一块。核心包里 actions.ts 的ActionBinding结构给出了生产级动作该有的所有维度export interface ActionBinding { /** Action name (must be in catalog) */ action: string; /** Parameters to pass to the action handler */ params?: Recordstring, DynamicValue; /** Confirmation dialog before execution */ confirm?: ActionConfirm; /** Handler after successful execution */ onSuccess?: ActionOnSuccess; /** Handler after failed execution */ onError?: ActionOnError; /** Whether to prevent default browser behavior (e.g. navigation on links) */ preventDefault?: boolean; }注意几个细节每个动作的params可以用 Zod schema 做参数校验ActionDefinition.paramsconfirm支持危险操作前的确认弹窗onSuccess/onError可以链式触发navigate、set状态或另一个动作。生产环境里删除这类动作必须配 confirm重路由必须经navigate而不是任意跳转参数必须过 schema。这些能力框架都给了不用等于没设护栏。第三张白名单是数据绑定边界。spec 里可以出现$state、$cond、$template、$computed这类动态表达式见 README.md 的 Dynamic Props 一节它们会读写你的 state model。这意味着 AI 理论上能读到的状态范围就是它能表达的状态范围。接入时我把它收窄成了只暴露业务需要的状态子树而不是把整个应用状态丢进去——$computed引用的是你注册的函数表同理只注册受控函数。坑二流式渲染——真正的挑战在于半行 JSON和部分 spec流式是 json-render 相对 A2UI 这类方案最明显的体验优势模型还在生成界面已经在一段一段地长出来。但把它跑稳比想象中难。SpecStream 的本质是 RFC 6902 patch 流核心包把流式格式叫SpecStream在 types.ts 里说得很直白每条 SpecStream 行都是一个 JSON patch 操作逐步构建出最终的 spec。解析一行就是严格判定它是不是合法的 patchexport function parseSpecStreamLine(line: string): SpecStreamLine | null { const trimmed line.trim(); if (!trimmed || !trimmed.startsWith({)) return null; try { const patch JSON.parse(trimmed) as SpecStreamLine; if (patch.op patch.path ! undefined) return patch; return null; } catch { return null; } }然后applySpecStreamPatch支持 RFC 6902 的全部六种操作add、replace、remove、move、copy、test。我最初天真地以为 AI 会一次性吐出一棵完整的 UI 树接入后才发现AI 是按路径一点一点补出这棵树的。理解这一点流式方案才算入门。半行缓冲第一个真正的生产级 bug从fetch拿到的是流式 chunk一个 JSON patch 很可能被切在任意位置。正确做法是先攒 buffer按换行符切行把最后一段不完整的行留回 buffer等下一个 chunk 到来再续上。官方 playground 的实现 use-playground-stream.ts 里正是这个模式buffer decoder.decode(value, { stream: true }); const lines buffer.split(\n); buffer lines.pop() ?? ; for (const line of lines) { const result parseLine(line.trim()); if (!result) continue; currentSpec applySpecPatch(currentSpec, result.patch); setSpec({ ...currentSpec }); }我踩过的版本是简单按行 split 直接解析结果在流式响应较快时频繁出现 JSON 解析失败——因为整行还没到齐。把最后一段lines.pop()留回 buffer是这个坑的唯一解药。另外逐条 patch 应用后要setSpec({ ...currentSpec })产生新引用否则 React 不会触发重渲染——use-playground-stream.ts 里每轮都强制展开。部分 spec 的渲染稳定性半成品也要能画出来流式的另一层挑战是AI 还没画完UI 就得先显示。一个只有root但elements还是空的对象一个children引用了尚未生成的节点都必须被安全地渲染成加载中而不是抛异常。官方在 React 渲染器 renderer.tsx 里对root缺失、elements[spec.root]不存在都做了兜底并提供loading/fallback参数同时用useElementSignatures(spec)做元素签名稳定化避免流式更新导致已渲染子树无谓重建。这个稳定性在 CHANGELOG.md 0.21.0 里被专门点名Stabilized streamed React renders and added coverage for incomplete streamed props and nested prop identities。生产接入时给Renderer的loading状态做骨架屏比任何优化都重要——用户在等 AI 出界面本身就是在等一个异步过程视觉反馈不能缺。编辑模式patch 之外的 merge 与 diff流式不只是生成还有改稿。playground 支持 JSONL 和 YAML 两种线格式YAML 模式下有 spec / edit / patch / diff 四种围栏edit 模式用deepMergeSpec合并、再用diffToPatches把差异转回 patch 流应用见 use-playground-stream.ts。diff 模式甚至允许 LLM 直接输出 unified diff服务端先 apply 再重新序列化。这些高级编辑模式每个都有自己的坑比如围栏闭合判定、合并结果的类型校验如果业务只需要生成 局部改稿起步阶段只放开 patch 模式就够了等链路稳定再逐步加 merge 和 diff。坑三组件白名单——不是限制而是给 AI 的受控词表第三个坑是关于 catalog 设计的。很多人包括最初的我自己把白名单理解成能开多少组件就开多少结果 AI 经常用错组件、传错 props或者在同一件事上有七八种表达方式。白名单条目要带使用说明书AI 对组件的理解取决于你在 catalog 里给了它多少上下文。看 playground 的实现 catalog.ts每个组件都配了description和example甚至会用否定句约束使用场景Card: { props: z.object({ title: z.string().nullable(), description: z.string().nullable(), maxWidth: z.enum([sm, md, lg, full]).nullable(), centered: z.boolean().nullable(), }), slots: [default], description: Container card for content sections. Use for forms/content boxes, NOT for page headers., example: { title: Overview, description: Your account summary }, },description会进系统提示词example则是少样本示例。这一行 NOT for page headers 看起来是给 AI 的实际上是在帮你减少一半的返工。写白名单本质上是在写 prompt engineering只是载体是 catalog。少即是多schema 越简单AI 越不出错catalog.ts 顶部有句非常务实的设计注释Keep schemas simple — one format per prop, no unions. Fewer components less confusion for the AI.我实际体会到的正是如此props 用z.union或过于自由的z.string()AI 会频繁生成边缘值而z.enum把可能值列死输出立刻稳定下来。白名单和 schema 的自由度要反着 AI 的随机性来设计——越随意越失控。结构校验与 autofix 兜底即使白名单设计得再好LLM 偶尔还是会产出结构错误的 spec。核心包的 spec-validator.ts 专门为AI 常见错误做校验检查项包括缺失 root、root 指向不存在的元素、children引用不存在的节点、把visible误放进props而不是元素顶层、孤立元素等等const result validateSpec(spec); if (!result.valid) { console.log(Spec errors:, result.issues); }更贴心的是autoFixSpec——比如children里的悬空引用会被直接修剪掉。生产接入建议在应用 patch 之后、交给渲染器之前做一次轻量校验把error级问题拦在渲染前warning级问题留作日志。另外如果走 LLM 结构化输出接口OpenAI/Gemini/Anthropicschema.ts 提供了catalog.jsonSchema()导出 strict JSON SchemaadditionalProperties: false、全部属性进required这个模式值得单独踩点——它直接决定了模型端结构幻觉的概率。给后来者的避坑清单最后把上面所有经验压缩成一份可以直接对照的清单安全边界三件套组件白名单、动作白名单、状态绑定边界三者都要显式收紧不要依赖框架默认安全动作必须有 schema confirm涉及副作用写库、跳转、删除的动作参数过z校验危险操作配确认弹窗onError一定要设计——AI 生成的 UI 触发失败动作时用户不该看到白屏流式解析必须做半行缓冲按\n切行最后一段留回 buffer每行解析失败要静默跳过而不是中断整个流每次 patch 应用后产生新 spec 引用用展开运算符触发 React 重渲染给Renderer配loading/fallback半成品 spec 会频繁出现视觉反馈不能缺白名单克制每个组件带descriptionexampleprops 优先z.enum和z.number()这类窄类型避免 union 和自由字符串校验 autofix 兜底patch 应用后过一遍validateSpec必要时autoFixSpec把 AI 的结构错误消化在渲染之前结构化输出优先能用catalog.jsonSchema()的 strict 模式就别让模型自由发挥纯文本输出起步只开 patch 编辑模式merge、diff、多围栏 YAML 这些高级模式等链路稳定再逐步放开。json-render 解决的是AI 生成 UI里最核心的工程问题把不可控的生成收敛成可组合、可校验、可流式的数据。它确实配得上Generative UI 框架的定位但框架给的是机制不是默认安全、默认稳定——这两样东西得靠接入方一坑一坑踩出来。希望这份清单能让你踩得少一点。【免费下载链接】json-renderThe Generative UI framework项目地址: https://gitcode.com/GitHub_Trending/js/json-render创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

MySQL存储引擎选型与InnoDB核心机制实战指南

MySQL存储引擎选型与InnoDB核心机制实战指南

做MySQL的故障排查和性能优化这些年,我越来越确认一件事:MySQL存储引擎不是建表时随便选个默认值的小事,而是整个数据库设计里最先要想清楚的地基。锁表、崩溃后数据丢失、count查询莫名慢、日志归档把磁盘撑爆,这些看起来八竿子打…

2026/10/12 1:16:49 阅读更多 →
Linux进程状态深度解析:运行、阻塞与挂起机制及排查实践

Linux进程状态深度解析:运行、阻塞与挂起机制及排查实践

1. 从一个真实场景说起:为什么你的进程监控脚本会“骗”你刚入行那会儿,我写过一个特别朴素的进程守护脚本,逻辑就一句话:每隔几秒扫一遍进程列表,如果目标进程不在了就拉起来。当时觉得这逻辑天衣无缝,直到…

2026/10/12 1:16:55 阅读更多 →
快手电脑版2026最新版Windows安装与兼容性深度指南

快手电脑版2026最新版Windows安装与兼容性深度指南

1. 项目概述:为什么“快手电脑版”安装这件事,远比看起来复杂得多“2026最新版快手电脑版下载与安装全攻略”这个标题,表面看是个再普通不过的软件安装教程,但作为连续三年深度参与多个主流短视频平台桌面端适配项目的从业者&…

2026/10/12 1:16:10 阅读更多 →

最新新闻

从MathCAD迁移到Maple Flow的完整实战复盘

从MathCAD迁移到Maple Flow的完整实战复盘

这次内部技术分享会,我把团队从 MathCAD 迁移到 Maple Flow 的完整过程做了逐段复盘——录像和配套的迁移手册、模板文件都已经打包放到资料区了,需要的同事直接下载。这篇文章是文字版精简稿,把为什么要迁、怎么迁、迁完之后踩过哪些坑&…

2026/10/12 9:09:39 阅读更多 →
C#上位机如何用OpenCvSharp实现USB摄像头H264录像

C#上位机如何用OpenCvSharp实现USB摄像头H264录像

简介:面向需要在C#中调用OpenCVSharp完成USB摄像头录像并以H264编码压缩的开发者,这份资源提供一套可运行的工程实现与配套项目文件。包内通过OpenCVSharp接入视频捕获设备,涵盖枚举摄像头、设置分辨率与帧率、指定H264编码器、逐帧转换写入以…

2026/10/12 9:08:38 阅读更多 →
开单软件二维码收款怎么用?从动态二维码到自动对账全解析

开单软件二维码收款怎么用?从动态二维码到自动对账全解析

管家婆易指开单支持二维码收款,这个更新对天天用开单软件跑业务的人来说,算是解决了一个老生常谈的痛点。以前最麻烦的不是开单本身,而是开完单之后那笔钱怎么收、什么时候收、收完怎么跟单子对上。我自己的使用场景是门店加外勤混着来&#…

2026/10/12 9:08:38 阅读更多 →
从 openai 迁移到 Kimi API 的官方教程:用 TaoToken 统一 Key 通道做兼容验证

从 openai 迁移到 Kimi API 的官方教程:用 TaoToken 统一 Key 通道做兼容验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 9:08:38 阅读更多 →
自进化的 Agent 记忆层 —— PowerMem 简易操作手册与 TaoToken 统一 Key 配置

自进化的 Agent 记忆层 —— PowerMem 简易操作手册与 TaoToken 统一 Key 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 9:08:38 阅读更多 →
PMP新考纲备考指南:高频考点与易错题全拆解

PMP新考纲备考指南:高频考点与易错题全拆解

1. 改版后的PMP考试,先认清题目长什么样不少人还停留在“PMP就是背背ITTO、记记五大过程组”的旧印象里,实际上2021年改版后的PMP考试早就换了一副面孔。我身边好几个朋友备考时还在啃老版教材,结果上了考场发现题目风格完全不对路&#xff0…

2026/10/12 9:08:38 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →