JSON Schema 校验:强制大模型生成合规的结构化数据

FreeGuideOnline 最新 2026-06-29

json { "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer", "minimum": 0 } }, "required": ["name"] }


这份 Schema 表示:数据必须是一个对象,有一个字符串类型的 `name` 属性(必填),和一个可选的整数类型 `age` 属性,且 `age` 不能小于 0。

## JSON Schema 基础语法

### 核心关键字

- `type`:指定数据类型,常用值有 `"string"`、`"number"`、`"integer"`、`"object"`、`"array"`、`"boolean"`、`"null"`。
- `properties`:定义对象的属性及其对应的子 Schema。
- `required`:字符串数组,列出必须出现的属性名。
- `additionalProperties`:是否允许对象中出现 `properties` 未定义的属性,默认 `true`。设置为 `false` 可严格限制结构。

### 数字与字符串约束

- 数字约束:
  - `minimum` / `maximum`:最小值 / 最大值。
  - `multipleOf`:必须是该值的倍数。
- 字符串约束:
  - `minLength` / `maxLength`:最小 / 最大长度。
  - `pattern`:正则表达式字符串,用于格式匹配。
  - `enum`:枚举值数组,数据必须为其中之一。

示例:一个包含约束的用户邮箱 Schema。

```json
{
  "type": "object",
  "properties": {
    "username": { "type": "string", "minLength": 3, "maxLength": 20 },
    "email": { "type": "string", "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" }
  },
  "required": ["username", "email"],
  "additionalProperties": false
}

数组约束

  • items:适用于数组中每个元素的 Schema。如果数组元素类型统一,直接传入一个 Schema;若需要元组模式,可传入数组。
  • minItems / maxItems:数组长度约束。
  • uniqueItems:布尔值,是否要求数组元素唯一。

示例:

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": { "type": "integer" },
      "name": { "type": "string" }
    },
    "required": ["id", "name"]
  },
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}

组合条件

可以使用逻辑关键字组合多个 Schema:

  • allOf:必须同时满足所有子 Schema。
  • anyOf:满足其中任意一个即可。
  • oneOf:必须满足恰好一个子 Schema。
  • not:不能匹配指定的 Schema。

例如,一个商品可以是电子书或实体书,用 oneOf 区分:

{
  "type": "object",
  "properties": {
    "title": { "type": "string" },
    "type": { "enum": ["ebook", "physical"] }
  },
  "oneOf": [
    {
      "properties": {
        "type": { "const": "ebook" },
        "file_size_mb": { "type": "number" }
      },
      "required": ["file_size_mb"]
    },
    {
      "properties": {
        "type": { "const": "physical" },
        "weight_kg": { "type": "number" }
      },
      "required": ["weight_kg"]
    }
  ]
}

如何编写有效的 JSON Schema

从需求出发,明确结构

  1. 写出你希望的数据范例。
  2. 标记每个字段的类型、约束、是否必填。
  3. 逐步添加验证规则(长度、范围、枚举、正则等)。
  4. 考虑边缘情况:空数组?缺失字段?多余字段?

使用工具进行实时校验

  • 在线验证器JSON Schema Validator 等。
  • 代码库:多数编程语言都有 JSON Schema 校验库(如 Python 的 jsonschema,Node 的 ajv)。建议编写单元测试确保 Schema 自身正确。

遵守最佳实践

  • 保持 Schema 可读,合理使用 $defs / definitions 重用结构。
  • 为每个 Schema 添加 titledescription 注解,便于生成文档。
  • 使用 additionalProperties: false 防止未声明的字段混入,尤其在与大模型集成时。

JSON Schema 与大模型结构化输出

为什么大模型需要 JSON Schema

大语言模型本质上是文本生成器,默认情况下输出自由文本。但在实际应用中,我们往往需要解析其输出,用于下游程序。通过 JSON Schema,可以:

  • 强制输出符合约定的 JSON 结构,避免解析失败。
  • 减少幻觉,因为模型被约束在特定字段和类型内。
  • 实现可靠的函数调用(Function Calling)和工作流自动化。

主流大模型 API(如 OpenAI、Anthropic)都提供了结构化输出模式,允许开发者传入 JSON Schema,模型保证生成的 JSON 完全符合 Schema。

实践:使用 OpenAI 的结构化输出

以 OpenAI GPT‑4o 为例,response_format 参数允许定义 json_schema

步骤

  1. 设计 JSON Schema 描述想要的输出。
  2. 在 API 请求中设置 response_format
  3. 直接从返回的 Parsed JSON 中读取数据。

示例:提取结构化地址信息

Schema 定义:

{
  "type": "object",
  "properties": {
    "country": { "type": "string", "description": "国家" },
    "province": { "type": "string", "description": "省份" },
    "city": { "type": "string" },
    "street": { "type": "string" },
    "postal_code": { "type": "string", "pattern": "^[0-9]{6}$" }
  },
  "required": ["country", "province", "city", "street"],
  "additionalProperties": false
}

API 调用(Python 风格示例):

from openai import OpenAI
client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "user", "content": "请解析地址:北京市海淀区中关村大街1号,100080"}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "address_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "country": {"type": "string"},
                    "province": {"type": "string"},
                    "city": {"type": "string"},
                    "street": {"type": "string"},
                    "postal_code": {"type": "string", "pattern": "^[0-9]{6}$"}
                },
                "required": ["country", "province", "city", "street"],
                "additionalProperties": false
            }
        }
    }
)

parsed = json.loads(completion.choices[0].message.content)
print(parsed)

得到的 parsed 一定是合法的 JSON 并且结构严格匹配 Schema,可以直接用于程序后续逻辑。

处理复杂结构与函数调用

在函数调用场景中,JSON Schema 被用来描述函数参数的形状。模型会根据用户输入,选择调用某个函数并生成符合 Schema 的 JSON 参数。

例如定义一个查天气的函数:

{
  "name": "get_weather",
  "description": "获取指定城市当前天气",
  "parameters": {
    "type": "object",
    "properties": {
      "city": { "type": "string", "description": "城市名称,如 'Beijing'" },
      "units": { "type": "string", "enum": ["celsius", "fahrenheit"] }
    },
    "required": ["city"],
    "additionalProperties": false
  }
}