登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

OpenAI API 怎样为结构化输出定义 JSON Schema

来源:17golang原创

时间:2026-10-26 02:38:48 101浏览 收藏

我第一次把模型输出接到业务对象时,最容易混淆的是“返回了合法 JSON”和“返回了符合业务结构的 JSON”。前者可以用 JSON mode,后者应该把 JSON Schema 交给 Structured Outputs,让接口约束字段形状。

官方文档:https://developers.openai.com/api/docs/guides/structured-outputs

Responses API 把配置放在 text.format,Chat Completions API 把配置放在 response_format。两种写法都要准备一个对象 Schema,并认真处理 required、additionalProperties 和拒答分支。

先分清两个请求入口

Structured Outputs 不是另一个独立的模型接口,而是请求体里的一组结构化输出配置。当前更适合新代码的 Responses API 使用 text.format;如果项目仍在使用 Chat Completions,则使用 response_format。两者共同指向 type: "json_schema" 和一份 Schema。

Responses API 与 Chat Completions API 通过不同字段承载 JSON Schema 的静态关系说明图
图1:结构化输出入口说明图,展示两个 API 请求入口与 JSON Schema 配置的静态关系。
调用入口配置位置关键字段
Responses APItext.formattype、name、schema、strict
Chat Completions APIresponse_formattype、json_schema、strict

用 Responses API 提交一份最小 Schema

下面的例子让模型返回一张工单摘要。字段数量故意保持很小:主题、优先级和是否需要跟进。这样更容易看清 Schema 本身,而不是被业务字段淹没。

import OpenAI from "openai";

const client = new OpenAI();

const ticketSchema = {
  type: "object",
  properties: {
    subject: { type: "string", description: "工单主题" },
    priority: { type: "string", enum: ["low", "normal", "high"] },
    follow_up: { type: "boolean" },
  },
  // Structured Outputs 要把对象字段全部列入 required。
  required: ["subject", "priority", "follow_up"],
  // 关闭额外字段,避免模型输出未声明的键。
  additionalProperties: false,
};

const response = await client.responses.create({
  model: process.env.OPENAI_MODEL ?? "gpt-6-astra",
  input: "把‘支付页面偶发超时,请跟进日志’整理成工单摘要。",
  text: {
    format: {
      type: "json_schema",
      name: "ticket_summary",
      strict: true,
      schema: ticketSchema,
    },
  },
});

// output_text 是 SDK 提供的文本聚合入口,业务层再按约定解析 JSON。
console.log(response.output_text);

这里最关键的不是把 JSON 写得很长,而是让每个对象层级都明确声明字段。name 是这份格式的标识,strict: true 表示按严格结构请求;enum 则把优先级限制在三个值内。

Schema 里最容易漏掉的三件事

我在迁移旧的 JSON mode 请求时,通常先检查下面三处。它们比“模型能不能返回花括号”更决定后续解析是否稳定。

JSON Schema 中 properties、required、additionalProperties 和 null 语义的静态边界说明图
图2:Schema 约束边界说明图,展示必填字段、额外字段和 null 语义如何影响结构化对象。

一是每个对象都要写 required

顶层对象要写 required,数组里的对象、嵌套对象也一样。Structured Outputs 的约束要求字段是必填的;如果业务上有“没有值”的情况,可以把字段声明为允许 null,但仍把它放进 required,这样返回对象的键集合仍然稳定。

{
  "type": "object",
  "properties": {
    "note": { "type": ["string", "null"] }
  },
  "required": ["note"],
  "additionalProperties": false
}

这段 JSON 不添加注释,以保持格式本身有效;note 的含义是“键一定存在,但值可以是字符串或 null”。

二是对象要关闭额外字段

additionalProperties: false 会把对象边界说清楚。不要只在顶层加它,嵌套对象也要按同样规则处理,否则下游 DTO、数据库映射或前端状态对象可能遇到未预期字段。

三是拒答不一定符合你的 Schema

用户输入触发安全拒答时,返回内容可能是 refusal,而不是你定义的对象。因此业务代码要先判断拒答或未完成响应,再把正常内容交给 JSON 解析器;Schema 约束解决的是正常结构,不替代安全分支和业务语义校验。

它和 JSON mode 到底差在哪

JSON mode 的目标是让结果成为合法 JSON,但不保证字段名、类型和嵌套结构都遵循你的设计。Structured Outputs 在可支持的 Schema 范围内进一步约束结构,所以当结果要直接驱动 UI、工单对象或数据管道时,我会优先采用它。

比较项JSON modeStructured Outputs
保证合法 JSON是是
保证遵循 Schema否是,仍受支持 Schema 范围限制
配置示例json_objectjson_schema + strict
适合场景只需要可解析 JSON需要稳定字段和类型的下游对象

如果使用 Chat Completions,配置形状可以写成下面这样。它是严格 JSON,所以不在代码块里插入注释;每一层对象仍需补齐 required 和 additionalProperties: false。

{
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "ticket_summary",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "subject": { "type": "string" },
          "priority": { "type": "string", "enum": ["low", "normal", "high"] },
          "follow_up": { "type": "boolean" }
        },
        "required": ["subject", "priority", "follow_up"],
        "additionalProperties": false
      }
    }
  }
}

我会怎样把它放进项目

我的习惯是先用一个小 Schema 打通“请求—解析—错误处理”三段,再逐步加入嵌套数组和枚举。字段命名尽量直观,重要字段补 description;不要一开始就把整个数据库对象原样搬进输出格式。

  • 需要稳定键集合:把字段列入 required,缺省值用 null 表达。
  • 需要防止模型扩展字段:每个对象都设置 additionalProperties: false。
  • 需要接 UI 或数据管道:单独处理 refusal、截断和 JSON 解析错误。

最后要记住,Structured Outputs 只负责输出结构,不会替你判断业务事实是否正确。Schema 设计得越小、字段描述越清楚,接入成本通常越低;当项目只是偶尔需要一段 JSON,JSON mode 可能已经够用。

相关问题

Responses API 的 Schema 放在哪里?

放在请求的 text.format 中,格式类型使用 json_schema,同时提供名称、Schema 和严格模式设置。

字段想表达“没有值”怎么办?

保留字段并允许它接受 null,不要把字段从 required 数组里删掉。

Structured Outputs 能替代业务校验吗?

不能。它约束 JSON 的形状,业务层仍要检查权限、数值范围、引用存在性和实际业务规则。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>