如何将AI转化为JSON格式再构建成用户界面?
摘要:背景 过去两年,AI 生成 UI 的实践基本集中在两种路径上。第一种是直接让模型生成 JSX、HTML 或 CSS。这条路线的优势在于自由度极高,模型几乎不受约束,看起来“什么都能写”。但在真实工程环境中,这种方式几乎不可控:输出结构不稳定
背景
过去两年,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 能力。
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 类型守卫与数据验证。
