Dify 中的 JSON Schema 标准与实战指南
一、什么是 JSON Schema?
JSON Schema 是一种基于 JSON 格式的声明式数据校验语言,它允许你描述一个 JSON 数据的结构、类型、约束条件。简单来说,JSON Schema 就是 JSON 数据的"模板"或"身份证"------它规定了数据应该长什么样。
一个直观的例子
假设你有一个用户数据:
json
{
"name": "张三",
"age": 25,
"email": "zhang@example.com"
}
对应的 JSON Schema 就是:
json
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 },
"email": { "type": "string", "format": "email" }
},
"required": ["name", "age", "email"]
}
这个 Schema 的含义是:
- 数据必须是
object类型 - 包含三个字段,各有类型约束
age最小值为 0email需符合 email 格式- 三个字段都必填
JSON Schema 的核心能力
| 能力 | 说明 |
|---|---|
| 类型校验 | string, number, integer, boolean, array, object |
| 必填校验 | required 数组指定哪些字段必须存在 |
| 范围约束 | minimum/maximum(数字)、minLength/maxLength(字符串) |
| 枚举约束 | enum 限定只能取特定值 |
| 正则校验 | pattern 对字符串做正则匹配 |
| 嵌套结构 | properties 和 items 支持任意深度的嵌套 |
| 条件校验 | if/then/else 实现条件逻辑 |
JSON Schema 目前有多个版本,最主流的两个是 Draft-07 (2019年)和 Draft 2020-12(最新版)。
二、Dify 中用到了哪些 JSON Schema 标准?
经过对 Dify 前后端代码的全面分析,JSON Schema 在 Dify 中出现在 6 大场景 中,涉及 20+ 个关键文件。
场景一:Chatflow Start 节点表单变量校验
这是最常用的场景------在 Chatflow 的 Start 节点中配置 json_object 类型变量,用 JSON Schema 约束用户输入。
| 环节 | 文件 | 作用 |
|---|---|---|
| 变量类型定义 | types.ts | InputVarType.jsonObject 枚举 |
| 变量配置弹窗 | config-modal | 编辑 json_object 变量的 Schema |
| Schema 标准化 | manager.py | _normalize_json_schema() 将 JSON 字符串转为 dict |
| 运行时校验 | graphon 包 (graphon/variables/input_entities.py) |
VariableEntity.json_schema 字段,在 StartNode._run() 中校验输入 |
标准版本 :Draft-07 (通过 jsonschema Python 库实现运行时校验)
Schema 基本结构要求:
json
{
"type": "object",
"properties": {
"字段名": { "type": "string", "description": "说明" }
},
"required": ["字段名"],
"additionalProperties": false
}
必须满足的约束 (来自 preValidateSchema 逻辑):
- 根节点必须是
type: "object" - 必须有
properties字段 required可选,值必须是字符串数组additionalProperties推荐设为false禁止未定义字段
测试用例覆盖(test_start_node_json_object.py):
- 合法 Schema 正常通过
- 类型不匹配(如
number传了字符串)→ 抛出ValueError - 缺少必填字段 → 抛出
ValueError - 字段缺失 → 抛出
ValueError - 非法 Schema 字符串 → Pydantic 校验失败
场景二:LLM 节点结构化输出(最完整的 UI 体系)
这是 Dify 中 JSON Schema 功能最丰富的场景,提供了完整的编辑器生态。
前端组件体系:
csharp
web/app/components/workflow/nodes/llm/components/json-schema-config-modal/
├── index.tsx # Modal 入口
├── json-schema-config.tsx # 主配置面板(两种编辑模式)
├── json-importer.tsx # 从示例 JSON 导入 Schema
├── schema-editor.tsx # 原始 JSON Schema 编辑
├── error-message.tsx # 错误显示
├── json-schema-generator/ # AI 生成 JSON Schema
│ ├── index.tsx
│ ├── prompt-editor.tsx
│ └── generated-result.tsx
└── visual-editor/ # 可视化编辑器(拖拽式)
├── index.tsx
├── schema-node.tsx
├── card.tsx
├── add-field.tsx
├── hooks.ts
├── store.ts
├── context.ts
└── edit-card/ # 字段编辑卡片
├── index.tsx
├── actions.tsx
├── advanced-actions.tsx
├── advanced-options.tsx
└── required-switch.tsx
标准版本 :Draft-07
验证流程:
javascript
JSON Schema 编辑 → JSON.parse → preValidateSchema → checkJsonSchemaDepth → validateSchemaAgainstDraft7
验证代码(utils.ts):
typescript
import { Validator } from 'jsonschema'
import draft07Schema from './draft-07.json'
// 使用 Draft-07 元 Schema 验证
export const draft07Validator = (schema: any) => {
return validator.validate(schema, draft07Schema)
}
// 禁止布尔属性(Dify 自定义规则)
export const forbidBooleanProperties = (schema: any, path: string[] = []): string[] => { ... }
// 预校验:必须是 { type: "object", properties, required?, additionalProperties? }
export const preValidateSchema = (schema: any) => {
return schemaRootObject.safeParse(schema)
}
深度限制 :index.ts 中定义 JSON_SCHEMA_MAX_DEPTH = 10,防止嵌套过深。
场景三:运行时表单(运行前填写)
当工作流运行时,用户需要填写 json_object 类型变量的值,Schema 会显示为占位提示。
| 文件 | 说明 |
|---|---|
| form-item.tsx | 工作流调试时,json_object 变量显示 Schema 作为占位提示 |
| content.tsx | 对话历史中的 JSON 输入表单 |
| content.tsx | 嵌入聊天机器人的 JSON 输入表单 |
| index.tsx | 文本生成模式的 JSON 输入 |
场景四:OpenAPI 外部调用接口
Dify 通过 OpenAPI 对外暴露应用时,会将 user_input_form 转换为 JSON Schema 供调用方参考。
标准版本 :Draft 2020-12(最新版)
python
# api/controllers/openapi/_input_schema.py
JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema"
类型映射表:
| Dify 表单类型 | JSON Schema 类型 |
|---|---|
text-input |
{ type: "string", maxLength? } |
paragraph |
{ type: "string", maxLength? } |
select |
{ type: "string", enum: [...] } |
number |
{ type: "number" } |
file |
{ type: "object", properties: { type, transfer_method, url, upload_file_id } } |
file-list |
{ type: "array", items: { file object } } |
⚠️ 注意 :
json_object类型在此处被跳过,因为它是内部校验而非外部输入。
测试用例:test_input_schema.py
场景五:MCP 服务
Dify 作为 MCP Server 时,将 json_object 变量的 Schema 映射到 MCP Tool 的 inputSchema 中。
文件:streamable_http.py
python
elif item.type == VariableEntityType.JSON_OBJECT:
parameters[item.variable]["type"] = "object"
if item.json_schema:
for key in ("properties", "required", "additionalProperties"):
if key in item.json_schema:
parameters[item.variable][key] = item.json_schema[key]
场景六:LLM 结构化输出调用
当 LLM 支持原生结构化输出时(如 GPT-4o、Gemini),Dify 将 JSON Schema 直接传给模型。
文件:structured_output.py
python
class ResponseFormat(StrEnum):
JSON_SCHEMA = "json_schema" # 原生结构化输出模式
JSON = "JSON" # JSON 模式
JSON_OBJECT = "json_object" # JSON 对象模式别名
工具参数 Schema :tool.py 的 get_llm_parameters_json_schema() 方法,将工具参数也转为 JSON Schema 供 LLM 理解。
场景七:dify-agent 独立 Agent 系统
dify-agent 是一个独立的 Agent 系统,它也使用 JSON Schema 来约束输出。
文件:output_layer.py
python
from jsonschema import SchemaError
from jsonschema.exceptions import ValidationError as JsonSchemaValidationError
from jsonschema.validators import validator_for
这里使用 Python 的 jsonschema 库在运行时真正做数据校验 ,将 JSON Schema 包装成 Pydantic AI 的 ToolOutput,实现模型输出与 Schema 的自动匹配。
总结:六大场景的 JSON Schema 标准一览
| 场景 | 标准版本 | 校验时机 | 校验工具 |
|---|---|---|---|
Chatflow 表单 json_object |
Draft-07 | 运行时用户输入 | jsonschema (Python) |
| LLM 节点结构化输出 | Draft-07 | 编辑时 + 运行时 | jsonschema (JS) + draft-07.json 元 Schema |
| 运行时表单展示 | Draft-07 子集 | 编辑时 | 前端展示 |
| OpenAPI 外部接口 | Draft 2020-12 | 仅输出描述 | 无校验 |
| MCP Tool | Draft-07 子集 | 透传给 LLM | 无校验 |
| dify-agent 输出层 | Draft-07 | 运行时校验 | jsonschema (Python) |
三、如何快速将手中的 JSON 转化为 JSON Schema?
方法一:在线工具(推荐,最快)
| 工具 | 地址 | 特点 |
|---|---|---|
| JSON Schema Generator | www.jsonschema.net/ | 可视化界面,拖拽配置,支持复杂嵌套 |
| Transform | transform.tools/json-to-jso... | 极简,粘贴即生成 |
| Liquid Technologies | www.liquid-technologies.com/online-json... | 支持多种 Draft 版本切换 |
操作示例 :粘贴以下 JSON 到 jsonschema.net
json
{
"name": "张三",
"age": 25,
"skills": ["Python", "TypeScript"],
"address": {
"city": "北京",
"zip": "100000"
}
}
自动生成:
json
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"skills": {
"type": "array",
"items": { "type": "string" }
},
"address": {
"type": "object",
"properties": {
"city": { "type": "string" },
"zip": { "type": "string" }
},
"required": ["city", "zip"]
}
},
"required": ["name", "age", "skills", "address"]
}
方法二:用 Dify 自带的 AI 生成器
在 LLM 节点 的结构化输出配置中,Dify 内置了 AI 生成功能:
- 点击 LLM 节点 → 输出变量 → 结构化输出
- 点击 "AI 生成" 按钮
- 用自然语言描述你想要的输出结构
- 点击生成,AI 自动输出 JSON Schema
⚠️ 注意 :Chatflow Start 节点的 json_object 变量配置中没有这个 AI 生成按钮,你可以先在其他地方生成好 Schema 再粘贴过去。
方法三:在 Dify 中使用可视化编辑器
在 LLM 节点的结构化输出中,选择 可视化编辑器 模式:
- 无需写任何 JSON,通过拖拽和表单填写即可构建 Schema
- 支持:添加字段、设置类型、配置必填、添加枚举值、嵌套子字段
- 适合非技术人员使用
方法四:Dify 内置的 JSON 导入功能
在 LLM 节点结构化输出的 JSON Schema 编辑器中,有一个 Import from JSON 功能:
- 粘贴一段示例 JSON 数据
- 系统自动推导出对应的 JSON Schema
- 可在可视化编辑器中进一步调整
方法五:速查模板(手动编写)
简单对象模板:
json
{
"type": "object",
"properties": {
"title": { "type": "string", "description": "标题" },
"count": { "type": "integer", "minimum": 0, "description": "数量" },
"tags": {
"type": "array",
"items": { "type": "string" },
"description": "标签列表"
},
"isActive": { "type": "boolean", "description": "是否激活" }
},
"required": ["title", "count"],
"additionalProperties": false
}
嵌套对象模板:
json
{
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": { "type": "string" },
"address": {
"type": "object",
"properties": {
"city": { "type": "string" },
"zip": { "type": "string" }
},
"required": ["city"]
}
},
"required": ["name"]
}
},
"required": ["user"]
}
枚举值模板:
json
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "active", "completed", "cancelled"],
"description": "状态"
}
},
"required": ["status"]
}
方法选择建议
| 场景 | 推荐方式 |
|---|---|
| 已有示例数据 | 方法一(在线工具)或方法四(Dify JSON 导入) |
| 知道字段和类型 | 方法五(速查模板) |
| 复杂嵌套结构 | 方法一(在线工具)或方法三(可视化编辑器) |
| 零基础非技术人员 | 方法三(可视化编辑器) |
| 需要在 Dify 中快速完成 | 方法二(AI 生成)或方法四(导入) |
| 批量生成或自动化 | 方法一(在线工具 API) |
四、常见问题与最佳实践
1. Chatflow 表单中 Schema 不生效?
检查是否满足以下条件:
- 在 Start 节点中 配置变量类型为
json_object(不是json) - Schema 根节点必须是
type: "object"(不能是type: "array") - 必须有
properties字段 - 用户输入必须是 JSON 对象(不能是字符串)
2. 如何限制用户只输入特定字段?
使用 additionalProperties: false 禁止未在 properties 中定义的字段:
json
{
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false // 禁止额外字段
}
3. 如何让 LLM 输出特定格式?
在 LLM 节点的结构化输出中使用 JSON Schema,Dify 会自动:
- 将 Schema 传给支持原生结构化输出的模型(GPT-4o、Gemini 等)
- 对不支持原生输出的模型,在 prompt 中注入 Schema 描述
- 运行时解析和校验 LLM 输出
4. 嵌套深度有限制吗?
有!JSON_SCHEMA_MAX_DEPTH = 10,超过 10 层嵌套会报错。
5. Draft-07 和 Draft 2020-12 有什么区别?
| 特性 | Draft-07 | Draft 2020-12 |
|---|---|---|
| Dify 使用场景 | 内部校验(表单、LLM 输出) | OpenAPI 外部接口 |
| 关键字 | $id, $schema 可选 |
$schema 必须 |
| 条件校验 | if/then/else |
支持 |
| 默认值 | 无单独关键字 | default 关键字 |
| 兼容性 | 广泛支持 | 较新,工具支持不如 Draft-07 广泛 |
建议:在 Dify 内部使用时都用 Draft-07 格式,它兼容性最好且所有场景都支持。