JSON Schema 不是一段普通 JSON,而是描述和验证数据结构的机器可读契约。本文从结构化输出、工具调用、MCP 协议和跨模型适配四个场景出发,说明如何设计主 Schema、供应商适配层与第二层业务校验。
Draft 2020-12 是 JSON Schema 当前公开规范版本之一,官方规范将它定义为描述 JSON 数据结构、进行验证和复用的机器可读文档。JSON Schema 官方规范 判断框:适合需要稳定输出、工具调用和跨模型复用的团队;不适合把 Schema 当成权限系统或业务真实性证明,因为它只约束数据形状。
这篇文章适合三类人: AI 应用开发者,需要定义稳定输出和工具参数。平台工程师,需要跨模型复用数据契约。测试工程师,需要建立自动验证和兼容性回归。
先分清:JSON Schema 和普通 JSON 的区别
普通 JSON 是数据本身。例如:
{
"status": "paid",
"amount": 99
}
它可以被解析,但没有说明 status 是否只能取固定值、amount 是否必须是数字、字段是否允许缺失。
JSON Schema 则描述“什么样的数据才算合格”:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "paid", "cancelled"]
},
"amount": {
"type": "number",
"minimum": 0
}
},
"required": ["status", "amount"],
"additionalProperties": false
}
这里的 type 定义类型,properties 定义字段,required 定义必填项,enum 限定允许值,additionalProperties 控制是否允许额外字段。JSON Schema 官方文档也建议在根节点写明 $schema,让工具知道目标规范版本。JSON Schema 入门示例
因此,合法 JSON 不等于符合 Schema。前者只代表语法能解析;后者代表字段、类型和约束都通过了结构验证。AI Agent 的下游代码真正需要的是后者。
这也是 JSON Schema AI Agent 体系中的基础分工:
- 模型负责生成候选数据。
- Schema 负责描述结构边界。
- 验证器负责判断结构是否合格。
- 执行器负责检查权限、资源和业务规则。
- 测试系统负责发现兼容性回归。
评分上,我们给 JSON Schema 在“字段稳定性”上评 5 / 5,在“业务真实性”上只给 2 / 5。后一个分数很低,是因为 Schema 无法知道订单是否属于当前用户,也无法确认数据库里真的存在某个资源。
第一种场景:结构化输出依赖 Schema 限定结果形状
在信息抽取、分类、路由和 Agent 状态机中,模型输出往往要直接进入程序。如果输出只是自然语言,程序需要额外编写解析逻辑,遇到字段缺失、类型变化或枚举拼写错误就会失败。
以工单分类为例,团队通常希望得到:
{
"category": "billing",
"priority": "high",
"needs_human": true
}
Schema 可以规定:
category必须是字符串;priority只能是low、normal或high;needs_human必须是布尔值;- 三个字段都必须存在;
- 不接受模型额外生成的解释字段。
OpenAI 的 Structured Outputs 文档明确说明,启用严格模式时只支持 JSON Schema 的一个子集,而不是完整规范。OpenAI Structured Outputs 说明
Gemini 的结构化输出同样支持 JSON Schema 子集,官方列出的基础类型包括 string、number、integer、boolean、object、array 和 null。Gemini Structured Output 官方文档
JSON Schema 和普通 JSON 的区别,核心不在文件后缀,而在是否存在可验证的结构契约。模型可能返回语法正确但契约错误的数据,例如把金额写成字符串,把枚举写成未定义的值,或者漏掉执行器必需的字段。结构化输出模式能降低这类问题,但应用端仍应执行一次独立验证,不能只相信模型返回成功。
这里建议把验证拆成两层:
- 结构验证:检查类型、字段、枚举、数组长度和额外属性。
- 业务验证:检查日期是否存在、订单是否归属当前用户、金额是否在业务范围内、状态转换是否合法。
例如,"order_id": "A1001" 通过 Schema,只能证明它是字符串。它不代表订单 A1001 存在,更不代表当前用户有权查看。
第二种场景:Function Calling 使用 Schema 描述工具参数
工具调用的关键不是让模型“写一段 JSON”,而是让模型生成可以交给执行器处理的参数对象。
例如,查询订单工具可能定义:
{
"name": "get_order",
"description": "查询当前用户有权访问的订单",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单编号"
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
模型根据这个 Schema 生成参数,执行器收到后再做三件事:
- 先验证
order_id是否为字符串; - 再检查订单是否存在;
- 最后检查当前身份是否有访问权限。
OpenAI 的函数工具定义使用 JSON Schema 描述参数,并在严格模式下要求模型遵守所给 Schema 的子集。OpenAI Function Calling 参数说明
Claude 的工具定义也要求提供 input_schema,用于描述工具预期接收的参数;官方文档还说明,可以使用严格工具调用来要求输入匹配 Schema。Claude 工具定义文档
为什么 Schema 不能代替权限控制? 因为 Schema 只描述“参数长什么样”,不描述“谁可以调用”。即使参数通过验证,执行器仍需检查身份、租户、资源归属、速率限制和幂等性。
为什么 Schema 不能保证参数对应真实资源? 因为 order_id、file_path 或 server_id 的真实性依赖数据库、文件系统或远程 API。Schema 只能判断它是字符串,不能替应用访问真实数据源。
我们在工具平台中更倾向于把权限检查放在执行器内部,而不是写进提示词。提示词可以说明规则,但不能成为安全边界。
第三种场景:MCP 同时约束工具输入与输出
Model Context Protocol 把工具暴露、工具发现和调用结果放进统一协议。MCP 工具定义包含 name、description、inputSchema,还可以提供 outputSchema。MCP Tools 官方规范
inputSchema 约束模型或客户端提交给工具的参数。例如:
{
"name": "search_logs",
"inputSchema": {
"type": "object",
"properties": {
"keyword": { "type": "string" },
"limit": { "type": "integer", "minimum": 1 }
},
"required": ["keyword"]
}
}
outputSchema 则描述工具返回结果的结构。工具可以将结构化结果放入 structuredContent,客户端再依据 outputSchema 验证。MCP 官方规范指出,如果工具提供了输出 Schema,服务器返回的结构化结果应符合该 Schema,客户端应进行验证。
这里要注意一个边界:MCP 负责工具暴露和调用协议,不负责替模型决定调用哪个工具。模型侧的工具选择仍由具体模型 API、客户端编排逻辑和 toolChoice 策略决定。
MCP 还存在版本和实现差异。当前规范页面仍需要结合具体协议版本阅读;部分较新的提案正在推动 inputSchema、outputSchema 和 structuredContent 更完整地对齐 JSON Schema 2020-12,因此不能看到“支持 JSON Schema”就推断所有关键字、引用和组合逻辑都已可用。MCP Schema 参考
⚠️ 经验提醒:MCP 工具返回结构化内容时,最好同时保留可序列化的文本回退。这样旧客户端或只处理文本的链路仍有机会继续工作。
第四种场景:三家模型的支持范围存在差异
不能简单回答“三家模型是否支持完整 JSON Schema”。更准确的说法是:OpenAI、Gemini 和 Claude 都使用 JSON Schema 或其变体描述工具参数与结构化结果,但每家的接口名称、严格模式和支持子集不同。
主要差异包括:
- OpenAI 常见字段是
parameters或结构化响应格式,严格模式只接受支持子集。 - Gemini 的
responseSchema或相关结构化输出接口也只支持 JSON Schema 子集,官方文档列出了可用基础类型和对象属性。 - Claude 工具输入使用
input_schema,工具调用可以返回tool_use;严格工具使用能力由具体接口和模型版本决定。 - MCP 的
inputSchema与outputSchema属于协议字段,不等于任意模型 API 的原生 Schema 字段。
一套 JSON Schema 能不能直接跨平台复用? 简单对象通常可以。涉及 $ref、$defs、条件组合、复杂 oneOf、正则表达式、默认值或额外属性策略时,不建议直接复制。
我们建议维护三层文件:
schemas/
order-result.master.json
adapters/
openai/order-result.v1.json
gemini/order-result.v1.json
claude/order-result.v1.json
mcp/order-result.v1.json
tests/
order-result.compatibility.json
主 Schema 表达完整业务契约。适配版本只保留目标平台稳定支持的关键字。每次转换都保存:
- 来源 Schema 版本;
- 目标接口和模型版本;
- 被删除或降级的关键字;
- 转换原因;
- 正例、反例和回滚版本。
这样做的重点不是追求“一份文件跑遍所有平台”,而是让差异可追踪、可测试、可回滚。
第五步:建立可维护的 Schema 治理流程
我们建议按下面 5 步 落地。
1.先定义业务对象,不要先迎合某个平台
先写出内部主 Schema,明确字段命名、类型、必填项、枚举值和错误结构。不要因为某个平台暂时不支持 $ref,就直接删掉业务层的复用关系。
2.把结构校验和业务校验分开
结构验证器只判断 JSON 是否符合 Schema。订单归属、用户权限、库存状态和金额计算放进业务服务。两个结果要分别记录,避免把“Schema 校验通过”写成“业务操作成功”。
3.为每个平台生成适配版本
适配层可以把复杂引用展开,把不支持的组合逻辑改成更简单的对象结构,或者将某些约束移动到执行器。每次降级都应写入转换日志,而不是静默修改。
4.准备正例、反例和边界样例
至少覆盖对象、数组、枚举、引用、额外属性、缺失字段、错误类型和空值。对于跨平台接口,还要记录模型、API 版本和调用日期。平台文档会变化,测试记录不能只保留“通过”两个字。
5.把 Schema 测试接入 CI
每次修改主 Schema 时,自动生成各平台版本并执行:
- Schema 本身是否能被验证器加载;
- 正例是否全部通过;
- 反例是否全部被拒绝;
- 模型输出能否被解析;
- 工具执行器是否拒绝未知字段;
- 旧版本数据是否仍能读取。
如果团队需要在 macOS 环境中持续运行这类测试,也可以先阅读 Mac 远程使用与连接帮助,再根据流水线的持续时间评估执行节点。对于需要长期维护的远程开发环境,建议同时查看 ZekVPS 服务条款,确认数据、权限和使用边界。
跨平台 Schema 的承载方案对比
下面这张表用于做初始架构选择。它不是“谁更强”的排名,而是帮助我们判断哪一层应该保存主契约、哪一层负责适配。
| 方案 | 主要作用 | Schema 位置 | 适合场景 | 主要风险 | 决策评分 |
|---|---|---|---|---|---|
| 内部主 Schema | 保存完整业务契约 | 独立代码仓库 | 多模型、多工具平台 | 不能直接保证平台兼容 | 5 / 5 |
| OpenAI 适配版本 | 约束结构化输出或函数参数 | 请求体或工具定义 | 严格输出、Function Calling | 只支持 JSON Schema 子集 | 4 / 5 |
| Gemini 适配版本 | 约束结构化响应和工具输入 | 结构化输出配置 | 数据抽取、Agent 工具链 | 需要按官方支持列表裁剪 | 4 / 5 |
| Claude 适配版本 | 描述 input_schema 和工具输入 | 工具定义 | 工具调用和多轮 Agent | 输入与输出处理方式不同 | 4 / 5 |
| MCP Schema | 约束协议中的工具输入与结果 | inputSchema、outputSchema | 工具发现、跨客户端调用 | 协议版本和客户端实现可能不同 | 4 / 5 |
| 业务验证层 | 判断真实资源与权限 | 执行器或服务端 | 订单、账户、文件、任务 | 不能被模型侧 Schema 替代 | 5 / 5 |
如果只是单模型、单工具、低风险脚本,直接写一份简化 Schema 可能足够。如果是多模型 Agent、MCP 工具市场或持续集成平台,我们更建议采用“主 Schema+供应商适配+回归测试”的结构。
真正容易出问题的不是字段少,而是团队没有记录“为什么删掉某个关键字”。半年后换模型、换协议版本,开发者就无法判断这是业务决定,还是某个平台的临时限制。
对于需要批量验证 Schema 的团队,当前本地方案或普通云主机常见的缺点是:环境依赖难以固定、macOS 专属测试无法直接复现、开发者个人电脑离线后流水线会中断。若测试任务涉及 Xcode、iOS 模拟器或 macOS 专属 CI,长期把这些工作塞进 Windows 或 Linux 环境并不是最佳方案。更稳妥的做法,是先把 Schema 转换和回归流程标准化,再根据任务是否持续运行决定是否配置 ZekVPS 的远程 Mac 节点;需要临时验证、短期迁移或跨平台测试时,这种方式通常比立即购买一台专用 Mac 更灵活。ZekVPS Mac 远程方案入口
用 ZekVPS 远程 Mac,加速你的 AI 工具链开发
为 JSON Schema、结构化输出与 MCP 工具调用准备一台可随时访问的远程 Mac。
ZekVPS 提供 Mac VPS、Mac VDI 与 Mac mini 租用方案,按需选择配置和地区,兼顾开发效率与使用成本。
若你正准备把 MCP 或 Agent 从 Demo 推到日常运转,先固定一台可快照的云 Mac 节点往往比换第五个框架更有效。 查看 ZekVPS 云端 Mac mini 套餐 — 把实验环境和生产桌面拆开,部署会踏实很多。