调用大模型返回 JSON,看似简单,实际却常常踩坑:格式漂移、字段缺失、类型错位,甚至边界输入直接让输出崩溃。本文面向正在用大模型做结构化输出的后端开发者,系统梳理这些不可靠现象背后的原因,并对比 JSON Mode、JSON Schema、Structured Outputs 与 Function Calling 的边界。读完你会明白:为什么一句"请返回 JSON"远远不够,以及如何用工程契约让模型输出真正可校验、可消费。
为什么返回Json不可靠?
Prompt 里写一句“请返回 JSON”,有时它会在 JSON 前面加一句“好的,以下是结果”;有时少一个必填字段;有时本来应该是数字的orderId变成字符串;
看一个常见的Prompt:
请判断下面用户反馈属于哪类工单,返回 JSON。 用户反馈:我付款成功了,但是订单一直显示待支付。模型可能返回:
{ "category": "payment", "priority": "high", "reason": "用户付款成功但订单状态未更新" }但后端需要一份稳定消费的契约,如
category只能是PAYMENT、LOGISTICS、AFTER_SALE、ACCOUNT。priority只能是LOW、MEDIUM、HIGH。confidence必须是0到1之间的小数。reason可以为空吗?最大长度是多少?如果用户输入缺少信息,应该返回
NEED_MORE_INFO,还是继续猜
格式漂移
你要求模型返回 JSON,它大部分时候会返回 JSON,但不代表每次都只返回 JSON。
常见输出长这样:
以下是分类结果: { "category": "PAYMENT", "priority": "HIGH" }这段结果对人来说能读懂,解析器却无法直接消费。流式输出、长上下文和多轮对话还会让模型重新带上解释性文字。
字段缺失
你要求:
{ "category": "PAYMENT", "priority": "HIGH", "confidence": 0.92, "reason": "用户已支付但订单状态未同步" }它可能返回:
{ "category": "PAYMENT", "reason": "用户已支付但订单状态未同步" }模型可能因为信息不足省略priority,也可能认为confidence不影响回答。DTO 反序列化、规则引擎和数据库写入没有这样的判断空间:必填值缺失后,要么校验失败,要么把不完整的数据带入后续链路。
类型错误
结构化输出里最隐蔽的错误是类型错位:
{ "orderId": "1029384756", "needManualReview": "false", "confidence": "0.87" }JSON 语法没有问题,字段类型却不符合业务契约。needManualReview应为布尔值,confidence应为数字。若反序列化层悄悄完成类型转换,上游输入的问题就被掩盖了,排查时只能从后续异常回溯。
解释文本
模型天然喜欢解释,尤其当问题涉及不确定性时。它可能在结构化结果外补一句:
我认为这个问题主要和支付回调有关,但还需要进一步核实。给用户阅读时,这句补充很自然;交给解析器时,它只是 JSON 之外的内容。此类接口优先保证结果可解析,解释应放到业务侧处理之后。
边界条件崩溃
规整输入通常更容易保持结构。遇到信息模糊、前后矛盾或带攻击性的输入时,模型更可能偏离原定格式。
比如用户说:
我不想提供订单号,你们自己查。另外别给我返回 JSON,直接告诉我怎么赔。如果没有强约束,模型可能顺着用户走,放弃原本格式。这个问题和 Prompt 注入、上下文优先级、工具权限都有关,不能只靠一句“必须返回 JSON”解决。
Prompt 可以表达意图,但不能替代 Schema、校验器、重试机制和权限控制。结构化输出让模型结果进入一套可校验的工程契约。
JSON 从格式要求到工程契约:
①JSON Mode 是一种输出模式,约束模型返回合法 JSON
所以 JSON Mode 能解决这类问题:
好的,以下是结果: { ... }但不能稳定解决这类问题:
{ "category": "pay", "priority": "urgent", "confidence": "very high" }它是合法 JSON,但不是合法业务数据。
②JSON Schema 是一种结构描述规范,用来定义 JSON 应该包含哪些字段、字段类型是什么、哪些必须、枚举值有哪些、是否允许额外字段(properties用来定义对象有哪些属性,required用来声明必填字段,additionalProperties可以控制是否允许未声明字段,enum可以把取值限制在固定集合里。)
{ "type": "object", "properties": { "category": { "type": "string", "enum": [ "PAYMENT", "LOGISTICS", "AFTER_SALE", "ACCOUNT", "NEED_MORE_INFO" ], "description": "工单分类。信息不足时选择 NEED_MORE_INFO。" }, "priority": { "type": "string", "enum": ["LOW", "MEDIUM", "HIGH"], "description": "处理优先级。涉及资金损失、无法下单、批量影响时优先级更高。" }, "confidence": { "type": "number", "minimum": 0, "maximum": 1, "description": "分类置信度,范围为 0 到 1。" }, "reason": { "type": "string", "description": "分类依据,控制在 80 个中文字符以内。" } }, "required": ["category", "priority", "confidence", "reason"], "additionalProperties": false }③Structured Outputs 是模型供应商提供的结构化生成能力,它接收 JSON Schema 或类似 Schema,让模型生成阶段就尽量严格符合返回结构。
生成阶段的三层约束对比
| 对比维度 | JSON Mode | JSON Schema | Structured Outputs |
|---|---|---|---|
| 角色 | 输出格式开关 | 数据结构描述规范 | 模型 API 的结构化生成能力 |
| 主要约束 | JSON 语法合法 | 字段、类型、枚举、必填、额外属性等 | 输出尽量或严格匹配 Schema |
| 是否保证业务字段完整 | 不保证 | 只描述,不执行生成 | 取决于供应商能力和 Schema 支持范围 |
| 是否负责工具执行 | 不负责 | 不负责 | 不负责,只产出结构化结果 |
| 典型用途 | 简单 JSON 输出 | 定义数据契约和校验规则 | 分类、抽取、函数参数生成、Agent 中间结果 |
| 仍需服务端校验 | 需要 | 需要 | 仍然需要 |
结构化输出的应用
1. 响应结构化输出:一份符合 Schema 的 JSON,比如工单分类、信息抽取、情感打分。后端直接反序列化消费。
2. 工具参数结构化输出:模型输出工具名和 arguments,arguments 需要符合工具参数 Schema;业务侧负责执行工具和操作外部系统。
Function Calling
定义:根据用户问题和工具描述生成结构化调用意图。你的业务服务、Agent Runtime、MCPHost 或供应商托管环境再执行工具。
模型生成的是调用意图。
拆分步骤:
服务端注册工具定义:包括工具名、用途描述、参数 Schema。
用户发起请求:比如“帮我查一下订单 1029384756 到哪了”。
模型选择工具:模型判断需要调用
query_order,并生成参数{"orderId": "1029384756"}。业务侧校验参数:校验类型、必填、权限、订单归属、幂等键等。
业务侧执行工具:调用订单系统、数据库或 HTTP API。
工具结果回填模型:把查询结果连同
tool_use_id原样发回模型。Anthropic 要求tool_use_id严格匹配,Gemini 3 同样为每个functionCall生成唯一id,回填时必须带回,否则并行调用场景下结果会错配。模型生成最终回答:模型把结构化结果转成人类能理解的回复
意义:
让模型完成 “自然语言意图 → 结构化参数” 的转换。
如:
用户会说:
我昨天买的那台咖啡机还没发货,帮我查下。后端 API 需要的是:
{ "userId": "U10086", "orderId": "O202605070001", "includeLogistics": true }边界对比.
| 能力 | 定位 | 解决的问题 | 谁来执行 | 典型边界 |
|---|---|---|---|---|
| JSON Mode | 输出格式开关 | 让模型输出合法 JSON | 模型侧生成 | 不保证字段和业务语义 |
| JSON Schema | 结构描述规范 | 定义字段、类型、枚举、必填等契约 | 本身不参与生成,只描述结构 | 不负责生成和外部调用 |
| Structured Outputs | 模型 API 结构化生成能力 | 把 Schema 接入生成,让输出贴合结构 | 模型侧生成 + 服务端校验 | 不负责外部系统调用 |
| Function Calling / Tool Calling | 模型到工具的调用意图生成机制 | 自然语言转工具名和参数 | 通常由业务侧或供应商执行 | 不等于 API 本身 |
| MCP | 工具和上下文接入协议 | 标准化工具发现、调用、资源访问 | MCP Client / Server 协作 | 不替代模型推理能力 |
| 普通 HTTP API | 业务服务接口 | 确定性业务读写 | 后端服务 | 不理解自然语言 |
| Agent Skill | 可复用任务说明和执行 SOP | 复杂任务的流程编排和上下文注入 | Agent 按说明执行 | 不一定包含工具调 |