OpenAI Responses API 怎样用结构化输出约束 JSON 形状
来源:17golang原创
时间:2026-10-24 20:14:06 168浏览 收藏
我第一次把一个已有的 JSON 抽取调用迁到 Responses API 时,最容易混淆的不是 Schema 本身,而是约束参数的位置:旧的 Chat Completions 写在 response_format,Responses API 则写在 text.format。如果还把旧的 json_schema 外壳原样搬过来,请求就会在参数层面走偏。
官方地址:https://developers.openai.com/api/docs/guides/structured-outputs
在 Responses API 中,使用text.format.type = "json_schema",把名称、Schema 和strict: true放到同一层;严格对象通常还要写全required和additionalProperties: false。这样约束的是输出形状,不是业务字段的真实性。
从旧请求迁移时,先改参数层级
OpenAI 官方把 Structured Outputs 和旧 JSON mode 区分开:两者都能产生合法 JSON,但只有 Structured Outputs 会按提供的 Schema 约束形状。Responses API 的结构化文本输出使用 text.format,因此迁移时应做一次字段对照。

| 旧写法 | Responses API 写法 | 迁移注意 |
|---|---|---|
response_format | text | Responses API 把输出配置放进 text |
json_schema.name | text.format.name | 名称必须是可用的短标识 |
json_schema.schema | text.format.schema | Schema 内容本身可以继续复用 |
json_schema.strict | text.format.strict | 严格模式只支持 JSON Schema 的一部分能力 |
这里的“复用 Schema”指复用 properties、required 等设计,不是把包含 name、schema、strict 的旧包装对象整体嵌套到 text.format 里。
严格 Schema 要把可选性写成数据类型
严格模式下,我会先把输出对象画成一张小表:字段名、类型、是否允许为空、允许的枚举值。对象字段写进 required,同时关闭额外属性;业务上“可能没有值”的字段仍然可以是必填字段,但类型声明为包含 null 的联合类型。
const ticketSchema = {
type: "object",
properties: {
category: {
type: "string",
enum: ["billing", "technical", "other"]
},
priority: {
type: "string",
enum: ["low", "normal", "high"]
},
summary: { type: "string" },
customer_id: {
// 没有客户编号时返回 null,但字段仍然必须出现
type: ["string", "null"]
}
},
// 严格对象把所有可返回字段明确列出,避免模型临时添加键
required: ["category", "priority", "summary", "customer_id"],
additionalProperties: false
};
这个 Schema 解决的是“返回哪些键、每个键是什么类型”。它不能保证 summary 的内容真实,也不能替业务系统完成权限、金额或状态校验;这些仍要在应用层处理。
把 Schema 放进 Responses API 的 text.format
下面是 Node.js SDK 风格的最小调用。示例只展示请求结构,密钥从环境变量读取;response.output_text 是供应用继续处理的文本结果,拿到后仍要根据响应状态和拒答信息决定是否解析。
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await client.responses.create({
model: "gpt-4o-mini",
input: [
{
role: "system",
content: "把工单归类并返回结构化结果。"
},
{
role: "user",
content: "用户说:发票下载失败,但订单已经完成。"
}
],
text: {
format: {
type: "json_schema",
name: "support_ticket",
strict: true,
schema: ticketSchema
}
}
});
// 正常完成后才把结构化文本交给业务层解析
const ticket = JSON.parse(response.output_text);
console.log(ticket.category, ticket.priority);
如果项目采用的 SDK 版本支持更高层的解析辅助,也可以使用对应 SDK 的类型化入口;但迁移的核心仍然是请求体中的 text.format 形状。模型是否支持 Structured Outputs、Schema 子集是否被接受,也应作为部署前的兼容性检查项。
拒答和不完整响应不能直接 JSON.parse
结构化输出并不意味着每一次响应都必然是业务对象。官方文档特别说明,模型拒答时可能返回不符合给定 Schema 的 refusal;响应状态也可能是 incomplete。因此,生产代码应把“请求成功”“模型愿意回答”“输出完整”“文本可解析”拆成几层判断。

function parseStructuredResponse(response) {
// 不完整响应先返回可诊断状态,不把残缺文本当作 JSON
if (response.status !== "completed") {
return { ok: false, reason: `response-${response.status}` };
}
// 拒答属于模型决策分支,不应强行按业务 Schema 解析
const refusal = response.output
?.flatMap((item) => item.content ?? [])
.find((part) => part.type === "refusal");
if (refusal) {
return { ok: false, reason: "refusal", message: refusal.refusal };
}
try {
// JSON 语法正确仍需由应用层检查枚举、权限和业务含义
return { ok: true, value: JSON.parse(response.output_text) };
} catch (error) {
return { ok: false, reason: "invalid-json", error };
}
}
上面的代码只负责分流,不代表 Schema 已经覆盖所有业务规则。比如 category 是允许的枚举值,不等于工单真的属于该分类;落库前仍应做白名单、长度、权限和状态机检查。
我会用这张清单做迁移回归
- 把旧请求中的
response_format改为 Responses API 的text.format,不要保留多余的json_schema包装层。 - 确认
type是json_schema,并给格式定义设置稳定名称;需要严格形状时显式使用strict: true。 - 逐个检查对象的
required和additionalProperties: false;业务可选值用null表达。 - 把拒答、不完整、空输出、JSON 解析失败分别记录,不把它们统一归类为“字段缺失”。
- 对旧模型、当前目标模型和实际 SDK 版本做一次兼容性确认,尤其关注 Strict Schema 支持子集。
- 最后再做业务校验:枚举白名单、字符串长度、身份权限、金额或状态转换不能交给 JSON Schema 单独承担。
对我来说,结构化输出最有价值的地方不是让模型“看起来像 JSON”,而是把接口边界前移到请求定义里。迁移时只要先改参数层级,再收紧 Schema,最后补齐失败分支,通常比在下游不断修补字符串解析更稳。
相关问题
Responses API 的 JSON mode 和 Structured Outputs 有什么区别?
JSON mode 主要保证结果是合法 JSON;Structured Outputs 还会按提供的 JSON Schema 约束形状。能使用 Schema 时,优先选择 json_schema。
严格模式下怎样表示可选字段?
可以让字段出现在 required 中,同时把类型写成例如 ["string", "null"],用 null 表示没有值。
Schema 严格通过后还要做业务校验吗?
要。Schema 约束类型和形状,不能替代权限、真实性、数值范围和业务状态检查。
参考地址:https://developers.openai.com/api/docs/guides/structured-outputs
-
284 收藏
-
387 收藏
-
328 收藏
-
426 收藏
-
147 收藏
-
119 收藏
-
346 收藏
-
101 收藏
-
246 收藏
-
118 收藏
-
489 收藏
-
469 收藏
-
439 收藏
-
239 收藏
-
491 收藏
-
114 收藏
-
319 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习