AI → JSON → UI

背景

过去两年,AI 生成 UI 的实践基本集中在两种路径上。第一种是直接让模型生成 JSX、HTML 或 CSS。这条路线的优势在于自由度极高,模型几乎不受约束,看起来“什么都能写”。但在真实工程环境中,这种方式几乎不可控:输出结构不稳定,无法保证组件边界,难以做权限与审计控制,生成的代码经常无法编译或违背工程约定,更重要的是,它与实际业务中的组件体系和设计系统严重脱节。

另一条路线是低代码或 schema 驱动 UI,例如基于 JSON Schema 或表单 schema 的方案。这类方案在工程上是可控的,结构稳定、可校验、可复用,但它们本质上是为“人编写配置”设计的,而不是为“模型生成结构”设计的。schema 表达能力有限,扩展成本高,并且与自然语言之间的映射并不自然,Prompt 往往需要大量人工约束。

Vercel 刚刚开源了 json-render,json-render 的出现,本质上是对这两条路线的重新切分与组合。它并没有试图让 AI 写前端代码,也没有把 AI 限制在传统低代码 schema 中,而是引入了一个中间层:JSON UI AST。AI 只能生成这种 AST,而 AST 的能力边界完全由开发者定义。渲染、状态、行为解释全部留在业务侧完成。开发者因此可以安全地让用户通过自然语言生成仪表盘、小部件或数据视图,而不需要把执行权交给模型。

整体架构:json-render 是一个 DSL 解释系统

从架构视角看,json-render 并不是一个 UI 框架,而是一个 DSL 执行系统。系统由三层构成:最底层是 Catalog,用来声明“系统允许 AI 使用哪些 UI 能力”;中间层是 JSON UI Tree,这是 AI 的唯一输出形式;最上层是 Renderer,由业务侧实现,用于解释 JSON 并渲染真实 UI。

它们之间的关系可以用下面这张结构图来理解:

┌────────────┐ │ Prompt │ └─────┬──────┘ │ ▼ ┌──────────────────┐ │ LLM / AI Model │ └─────┬────────────┘ │ JSON UI AST(受 Catalog 严格约束) ▼ ┌──────────────────┐ │ Catalog │ ← 能力白名单 / Schema / Grammar └─────┬────────────┘ │ 校验 + 解析 ▼ ┌──────────────────┐ │ Renderer │ ← React / Vue / Native └─────┬────────────┘ │ ▼ ┌──────────────────┐ │ Real UI View │ └──────────────────┘

在这个模型中,AI 只参与“结构生成”,不参与“执行”。这也是 json-render 在工程上成立的根本原因。

从 Catalog 到 UI

1. Catalog:系统的能力边界定义

下面这段代码是整个系统中最重要的入口,它定义了 AI 能使用的全部 UI 能力。

/* by 01130.hk - online tools website : 01130.hk/zh/calctime.html */ import { createCatalog } from '@json-render/core' import { z } from 'zod' export const catalog = createCatalog({ components: { Card: { props: z.object({ title: z.string() }), hasChildren: true }, Metric: { props: z.object({ label: z.string(), valuePath: z.string(), format: z.enum(['number', 'currency', 'percent']).optional() }) } }, actions: { refresh: { params: z.object({}) } } })

这里没有任何 UI 代码,只有能力声明。props 使用 Zod 定义,这意味着它不仅是类型提示,还包含运行时校验规则。如果你对 Zod 没有了解,可以看看这篇博文,Zod:TypeScript 类型守卫与数据验证。action 并不是函数实现,而是一个“意图声明”,它只描述“可以发生什么”,不描述“怎么发生”。

Catalog 在系统中的地位,相当于一门语言的语法定义文件。AI 后续生成的所有 JSON,本质上都必须符合这套 grammar。

2. AI 输出的 JSON UI AST

当用户输入类似“生成一个收入仪表盘”的提示时,模型生成的结果不是 JSX,而是下面这样的 JSON:

/* by 01130.hk - online tools website : 01130.hk/zh/calctime.html */ { "type": "Card", "props": { "title": "Revenue Overview" }, "children": [ { "type": "Metric", "props": { "label": "Total Revenue", "valuePath": "/metrics/revenue", "format": "currency" } } ] }

这个 JSON 有几个非常关键的特征。它不包含任何函数、不包含条件表达式、不包含样式或状态逻辑。它只是结构化地描述“使用哪个组件,用什么参数,组件之间如何嵌套”。所有能力完全来源于 Catalog,因此这个 JSON 是可校验、可存储、可 diff、可审计、可回放的。

3. Renderer:JSON 的解释执行

在 React 侧,Renderer 扮演的是解释器的角色。

import { Renderer } from '@json-render/react' import { catalog } from './catalog' function App() { return ( <Renderer catalog={catalog} components={{ Card: ({ title, children }) => ( <div className="card"> <h2>{title}</h2> {children} </div> ), Metric: ({ label, value }) => ( <div> {label}: {value} </div> ) }} data={{ metrics: { revenue: 120000 } }} /> ) }

Renderer 并不关心 UI 长什么样,它只做三件事:根据 type 找到对应组件定义,根据 Catalog 校验 props 和 children,根据 valuePath 等规则完成数据注入。

为什么 json-render 是“可控的”

下面的借助 AI 能力分析基于vercel-labs/json-render主仓库。如果你对此不感兴趣,跳过这部分内容。

1. createCatalog:能力被冻结的起点

文件路径位于packages/core/src/create-catalog.ts。这个函数的核心作用不是“注册组件”,而是“冻结能力边界”。

简化后的核心逻辑可以理解为:

export function createCatalog(definition) { return { components: definition.components, actions: definition.actions, validateNode(node) { // 校验 type 是否存在 // 校验 props 是否符合 Zod schema // 校验 children 是否被允许 } } }

每一行代码都在服务一个目标:让 Catalog 成为一个不可突破的白名单。Renderer 和 AI 都无法绕过它。这也是为什么 json-render 把 Catalog 放在 core 包中,而不是 React 包中。

2. Schema 校验:AI 输出必须“先编译再执行”

在 JSON Tree 进入 Renderer 之前,系统会逐节点校验。type 是否在 Catalog 中声明,props 是否通过 Zod 校验,children 是否符合 hasChildren 约束,action 是否存在于白名单。这一过程本质上就是一次 AST 校验。

这意味着 AI 的输出不是“运行时报错”,而是“不通过即拒绝执行”。在 AI UI 系统中,这是一个极其关键但经常被忽视的工程点。

3. Renderer:真正的解释器模型

React Renderer 的内部逻辑并不是简单的 switch-case,而是一个递归解释过程。它根据节点的 type 查 Catalog,构造 props,解析 valuePath 注入数据,绑定 action handler,然后递归渲染 children。

从架构角度看,它更接近一个 JSON AST Interpreter,而不是模板引擎。这也是 json-render 可以跨 React、Vue、Native 复用核心思想的原因。

4. valuePath:刻意避免 AI 参与状态逻辑

valuePath 使用字符串路径描述数据依赖,例如:

"valuePath": "/metrics/revenue"

这样设计的直接结果是,AI 不需要理解状态结构,也不需要写任何状态逻辑。Renderer 统一负责解析路径、读取数据、触发更新。这在架构上刻意切断了“AI 直接操作状态”的可能性。

下面是仅包含新增内容的补充章节,重点放在可落到源码层面的机制,避免概念化描述。示例代码与解释均基于vercel-labs/json-render当前仓库结构与实现思路。

Prompt 与 Catalog 的自动对齐

Prompt 与 Catalog 的自动对齐:不是“调 Prompt”,而是“导出 Grammar”。json-render 中,Prompt 与 Catalog 的对齐并不是通过人肉 Prompt Engineering 完成的,而是通过从 Catalog 派生一份机器可理解的能力描述,并将其注入到模型上下文中。这一点在packages/core中的设计非常关键。

在 core 层,Catalog 本身并不是一个简单的对象,它包含了完整的组件定义、props schema 以及 action 描述。这些信息会被转换为一种“描述性结构”,用于告诉模型当前系统支持的 UI grammar。

类似这样的逻辑:

export function catalogToPrompt(catalog) { return ` You can generate a JSON UI tree. Available components: ${Object.entries(catalog.components).map(([name, def]) => ` - ${name} props: ${describeSchema(def.props)} hasChildren: ${def.hasChildren} `).join('\n')} Available actions: ${Object.keys(catalog.actions).join(', ')} Rules: - Output must be valid JSON - Only use listed components - Follow prop schemas strictly ` }

这里的关键点不在于字符串本身,而在于信息来源完全来自 Catalog。换句话说,Catalog 是 single source of truth,Prompt 只是它的一种序列化视图。当开发者新增或修改组件定义时,Prompt 中允许模型使用的能力会自动发生变化,不存在“代码和 Prompt 不一致”的问题。这也是 json-render 能够避免大量“Prompt 腐化”的根本原因。

从模型视角看,它面对的不是一段模糊的自然语言说明,而是一套接近 BNF 的 UI grammar 描述。模型生成 JSON UI Tree 的过程,本质上类似于在给定语法约束下生成 AST。这也是为什么 json-render 要使用 Zod 而不是仅靠 TypeScript 类型。Zod schema 可以被同时用于运行时校验和 Prompt 语义描述,形成闭环。

Streaming UI 的实现细节

流式构建 AST,而不是流式拼字符串。json-render 的 Streaming UI 能力,核心并不在“模型支持流式输出”,而在于 UI 的中间表示是可增量合并的 JSON AST。这一点在 React 包中的实现非常清晰。

packages/react中,可以看到类似useUIStream的 hook,其核心职责是:
维护一棵当前 UI Tree,并在模型流式输出时不断向这棵树中合并新节点。

简化后的内部结构大致如下:

// packages/react/src/use-ui-stream.ts(概念结构) export function useUIStream() { const [tree, setTree] = useState<UITree | null>(null) function onChunk(chunk: string) { const partialNode = parseChunkToNode(chunk) if (!partialNode) return setTree(prevTree => { return mergeTree(prevTree, partialNode) }) } return { tree, onChunk } }

这里有两个非常关键但容易被忽略的点。

parseChunkToNode并不是简单的JSON.parse。模型在 streaming 模式下输出的通常是不完整 JSON,因此 json-render 采用的是逐段解析、延迟成型的策略。只有当一个节点在结构上是完整且通过 Catalog 校验时,才会被提升为“可合并节点”。mergeTree是一个纯函数。它不依赖外部状态,只根据已有 UI Tree 和新节点生成下一棵 Tree。这使得每一次更新都是确定性的,也天然适合 React 的状态模型。

在 Renderer 层,这棵 Tree 会被直接用于递归渲染:

function RenderNode({ node }) { const Component = components[node.type] const resolvedProps = resolveProps(node.props) const children = node.children?.map(child => <RenderNode key={child.id} node={child} /> ) return <Component {...resolvedProps}>{children}</Component> }

由于 Tree 始终是“已校验的合法结构”,Renderer 不需要关心节点是否完整,只需要关心“当前有哪些节点已经存在”。这也是 Streaming UI 能在生成未完成时就安全渲染的根本原因。

Streaming 与 Catalog 校验如何协同工作

Streaming UI 并不是绕过校验机制的捷径,恰恰相反,它依赖校验机制才能成立。在实际流程中,每一个候选节点在被合并进 UI Tree 之前,都会经过 Catalog 的校验逻辑:

// packages/core/src/validate-node.ts(概念结构) export function validateNode(node, catalog) { const def = catalog.components[node.type] if (!def) throw new Error('Unknown component') def.props.parse(node.props) if (node.children && !def.hasChildren) { throw new Error('Children not allowed') } }

Streaming 模式下,这个校验发生得更频繁,但粒度更小。系统宁可“暂时不渲染”,也不会把一个非法节点交给 Renderer。这保证了 UI 在任何时刻都是一个合法子集,而不是半成品垃圾状态。

Prompt 与 Catalog 的自动对齐,确保模型“不会幻想不存在的能力”;Streaming UI 的 AST 级增量构建,确保 UI“可以在不完整时仍然正确运行”。两者结合,使 json-render 的执行模型更接近编译器与解释器,而不是模板生成器。从工程视角看,这意味着一个重要转变:UI 生成不再是一次性结果,而是一个可观察、可中断、可回滚的过程。这也是 json-render 能够真正进入生产系统,而不仅停留在 Demo 层面的根本原因。

json-render 真正解决了什么

json-render 本身并不是一种全新的技术范式。“用受限结构描述 UI,再由运行时解释执行”这一思想,在前端工程中早已反复出现过。早期的 JSON Schema Form、react-jsonschema-form、Formily、本质上都是用结构化数据描述界面,再由渲染器生成真实 UI。低代码平台、搭建系统、配置化后台,几乎全部建立在同一逻辑之上。即便在 AI 出现之前,这种模式也已经非常成熟:工程师通过 schema 描述组件、属性和布局,运行时负责校验与渲染,业务侧只操作结构而不直接触碰代码。json-render 并没有发明这种模式,它继承的正是这一整条技术脉络。

json-render 的不同之处在于,它首次把“模型生成”作为一等公民纳入设计前提。传统 schema UI 假设配置由人编写,因此更强调完整性、可读性和编辑体验;而 json-render 假设结构由模型生成,因此更强调语法边界清晰、失败可恢复、部分结果可执行,以及与 Prompt 的自动对齐能力。从这个角度看,json-render 更像是“为 AI 重新设计的一代 schema UI 执行模型”。它真正解决的问题并不是“怎么用 JSON 渲染 UI”,而是当结构来源变成不可靠的模型时,工程边界应该在哪里。它给出的答案非常明确:AI 只负责生成结构化意图,工程师负责能力定义、执行与渲染,JSON 作为唯一中介和约束层。这使得 AI UI 不再是一次性 Demo,而是可以进入生产系统的工程能力。在当前阶段,这是少数真正站在工程立场思考 AI UI 的方案之一。

参考资料

  • json-render.dev
  • github.com/vercel-labs/json-render
  • vercel.com/blog
  • Zod:TypeScript 类型守卫与数据验证

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

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

相关文章

自建临时收件箱系统:Maildrop 开源项目服务器部署实战

如果你做过网站/APP 的登录注册、找回密码、订阅通知、工单系统,你一定懂这种痛点: 📩 测试邮件流程时,总得准备一堆测试邮箱 😵 邮箱账号切来切去,验证码/激活邮件经常找不到 🧪 CI 或回归测试需要“随用随有”的收件箱,但又不想依赖第三方 🔒 更别说有些邮件内…

自建 Status Page:Gatus 服务可用性监控面板搭建指南

如果你手上有不止一个网站/接口/节点,你一定经历过这种“很烦但又躲不开”的时刻: 😵 用户来问:“你们是不是挂了?”你还得先去自己打开页面确认 🧠 明明只是某个接口慢了,但你没有历史数据,根本说不清楚 📉 线上出问题经常是“你感觉不对劲”,但没有第一时间告警…

合规电商数据采集 API|多平台实时数据抓取,告别爬虫封号风险

一键采集亚马逊 / 速卖通 / 淘宝 / 京东全维度数据&#xff0c;赋能企业精准运营决策传统电商数据采集方式&#xff08;如爬虫、手动导出&#xff09;存在合规风险高、数据时效性差、格式不统一三大痛点&#xff1a;爬虫易触发平台反爬机制导致店铺封号&#xff0c;手动导出数据…

从功能测试到AI质量守护者:我的5年蜕变日记

第一章 功能测试的基石时代&#xff08;2021-2022&#xff09; 当我在2021年首次接触Jira缺陷管理系统时&#xff0c;手工测试仍是行业主流。每日重复着&#xff1a; graph LR A[需求评审] --> B[用例设计] B --> C[环境部署] C --> D[冒烟测试] D --> E[回归测试…

被遗忘的拼图:为什么你的身体每天都在“隐性饥饿”?

被遗忘的拼图&#xff1a;为什么你的身体每天都在“隐性饥饿”&#xff1f; ——揭秘甘氨酸的代谢缺口与长寿悖论 你是否曾有过这样的困惑&#xff1a;明明各项体检指标都还在“正常范围”&#xff0c;明明每天都在吃肉蛋奶&#xff0c;营养似乎并不匮乏&#xff0c;但身体却不…

Nginx 最核心和常用的命令

类别命令说明与常用参数&#x1f6e0;️ 服务管理​nginx启动 Nginx 服务。nginx -c <配置路径>使用指定的配置文件启动。nginx -s stop快速停止&#xff1a;立即终止所有进程&#xff0c;中断正在处理的请求。nginx -s quit优雅停止&#xff1a;等待当前连接的任务处理完…

C#——意框架(结构说明)

模块目录结构详解&#xff1a;基于DDD思想的工程分层设计一、整体框架说明本文将结合工程约定与模块模板&#xff0c;详细说明 module 目录下各常见子项目/文件夹的核心职责、放置内容及设计原则。以下结构适用于多数基于DDD&#xff08;领域驱动设计&#xff09;思想的分层架构…

【开题答辩全过程】以 基于大数据的旅游数据分析与可视化为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

学长亲荐10个AI论文平台,助继续教育学生轻松搞定毕业论文!

学长亲荐10个AI论文平台&#xff0c;助继续教育学生轻松搞定毕业论文&#xff01; AI 工具如何成为论文写作的得力助手&#xff1f; 在继续教育学生中&#xff0c;撰写毕业论文是一项既重要又棘手的任务。随着人工智能技术的不断发展&#xff0c;AI 工具逐渐成为提升论文写作效…

收藏!7年前端老鸟被AI震撼实录:零代码搞定项目后,我悟了大模型时代的生存法则

那天&#xff0c;我是真的被AI吓到了。 刚接到一个语音识别复刻的小程序开发需求&#xff0c;搁以前&#xff0c;从需求拆解到上线部署&#xff0c;至少得扎进去干个把星期。这次我没急着开干&#xff0c;先打开 Claude &#xff0c;把需求文档粘过去&#xff0c;跟它聊了聊核心…

医疗数据用Rust加速处理更稳

&#x1f4dd; 博客主页&#xff1a;jaxzheng的CSDN主页 Rust在医疗数据处理中的革命&#xff1a;加速与稳定的双轮驱动目录Rust在医疗数据处理中的革命&#xff1a;加速与稳定的双轮驱动 引言&#xff1a;医疗数据处理的双刃剑 一、医疗数据处理的核心痛点&#xff1a;为何Rus…

别再混淆了!AI Agent 与 Agentic AI 核心区别 + 落地指南,附大模型学习礼包

在大模型技术狂飙的当下&#xff0c;“智能体” 相关概念层出不穷&#xff0c;AI Agent和Agentic AI更是被频繁提及&#xff0c;却常常被混为一谈。 其实二者定位天差地别&#xff1a;AI Agent 是 “精准执行的智能助手”&#xff0c;专攻明确目标、固定流程的重复性任务&#…

【开题答辩全过程】以 基于Java的学生宿舍设备报修系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

收藏!50W+年薪大模型岗位逆袭指南:程序员/小白从0到1转型全攻略

近期&#xff0c;互联网与AI行业校招薪资再度刷屏热搜&#xff0c;其中「大模型链路开发」相关岗位的薪资格外抢眼——50万、60万甚至更高的年薪包&#xff0c;让无数应届生和职场新人直呼「神仙offer望尘莫及」。 但你可能不知道&#xff0c;斩获这些「黄金岗位」的并非全是应…

HarmonyOS中考试模板开发教程

考试模板开发教程 此模板已经上到组件商城 大家可以直接使用 本教程将教你如何使用 HarmonyOS 考试模板组件库快速开发一个功能完整的考试应用。 目录 项目概述环境准备项目结构快速开始创建考试数据题型详解自定义结果页面进阶功能 项目概述 本项目是一个 HarmonyOS 考试…

Java 多态详解:概念、实现机制与实践应用

文章目录一、什么是 Java 的多态二、多态成立的基本条件三、方法重写与多态的关系四、方法重载不是多态五、成员变量是否具有多态性六、static、final、private 方法与多态七、接口与抽象类中的多态八、JVM 层面&#xff1a;多态是如何实现的九、多态在实际开发中的价值十、总结…

别再被“能看图说话“骗了!真正能上线的多模态RAG,靠这4个关键细节+可运行代码

本文针对多模态检索中的"能力幻觉"问题&#xff0c;深度解析了Qwen3-VL-Embedding和Reranker的技术优势&#xff0c;详细阐述了多模态检索落地的4个关键工程断层及解决方案&#xff0c;包括完整pipeline设计、配置决策、模态指令应用和置信度校准等。文章提供可直接复…

收藏!大模型行业薪资真相:别追千万噱头,百万年薪才是务实赛道

大模型行业的高薪热度居高不下&#xff0c;不少技术人都想借此风口实现职业跃迁。但热潮之下更需理性&#xff1a;行业薪资确实可观&#xff0c;但绝非遍地千万。多数核心岗位年薪集中在40-150万区间&#xff0c;百万年薪已是行业主流核心水平&#xff1b;千万年薪仅属于硅谷顶…

大模型学习路线图全解析:程序员收藏必备,小白入门不迷路

文章提供了人工智能大模型的学习路线&#xff0c;包括基础知识、编程技能、深度学习、预训练模型研究和实践项目五个阶段。同时分享了640套AI大模型报告合集&#xff0c;涵盖理论研究、技术实现和行业应用。文章强调在AI时代成为掌握AI工具的技术人能占得先机&#xff0c;鼓励读…

从小白到专家:AI Agent十大应用领域深度解析,收藏这份大模型实践指南

AI Agent作为能自我学习、自动化处理的数字智能工具&#xff0c;正在催生新的产业价值链&#xff0c;并在软件开发、数字营销等十大领域应用。商业模式分为垂直场景型和通用平台型&#xff0c;尽管面临可靠性、安全与成本等挑战&#xff0c;AI Agent不仅是效率革新&#xff0c;…