You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在使用Pydantic创建嵌套JSON Schema时移除$defs和$ref?

如何移除Pydantic生成的JSON Schema中的*$defs和$ref*?

我通过以下代码用Pydantic生成JSON Schema:

from pydantic import BaseModel, Field
import json

class VendorInfo(BaseModel):
    vendor_name: str = Field("", description= "Vendor Name")
    vendor_vat_no: str = Field("", description= "Vendor VAT Number")

class InvoiceHeader(BaseModel):
    invoice_number: str = Field("", description= "The unique invoice number")
    invoice_date: str = Field("", description= "The date invoice was created")
    vendor_info: VendorInfo = Field("", description= "Description of the vendor")

print(json.dumps(InvoiceHeader.model_json_schema(), indent=2))

运行后得到包含*$defs和$ref*的输出:

{
  "$defs": {
    "VendorInfo": {
      "properties": {
        "vendor_name": {
          "default": "",
          "description": "Vendor Name",
          "title": "Vendor Name",
          "type": "string"
        },
        "vendor_vat_no": {
          "default": "",
          "description": "Vendor VAT Number",
          "title": "Vendor Vat No",
          "type": "string"
        }
      },
      "title": "VendorInfo",
      "type": "object"
    }
  },
  "properties": {
    "invoice_number": {
      "default": "",
      "description": "The unique invoice number",
      "title": "Invoice Number",
      "type": "string"
    },
    "invoice_date": {
      "default": "",
      "description": "The date invoice was created",
      "title": "Invoice Date",
      "type": "string"
    },
    "vendor_info": {
      "$ref": "#/$defs/VendorInfo",
      "default": "",
      "description": "Description of the vendor"
    }
  },
  "title": "InvoiceHeader",
  "type": "object"
}

请问如何移除生成Schema中的*$defs和$ref*,得到完全内嵌的结构?


解决方法

方法1:手动递归解析并替换引用

写一个递归函数遍历Schema结构,将所有*$ref指向的内容从$defs中取出并替换原引用字段,最后删除$defs*字段。

示例代码:

from pydantic import BaseModel, Field
import json

class VendorInfo(BaseModel):
    vendor_name: str = Field("", description= "Vendor Name")
    vendor_vat_no: str = Field("", description= "Vendor VAT Number")

class InvoiceHeader(BaseModel):
    invoice_number: str = Field("", description= "The unique invoice number")
    invoice_date: str = Field("", description= "The date invoice was created")
    vendor_info: VendorInfo = Field("", description= "Description of the vendor")

def dereference_schema(schema):
    def _deref(obj):
        if isinstance(obj, dict):
            if "$ref" in obj:
                # 提取引用的定义名称
                ref_name = obj["$ref"].split("/")[-1]
                ref_def = schema["$defs"][ref_name]
                # 保留原字段的额外属性(比如default、description)
                ref_def.update({k: v for k, v in obj.items() if k != "$ref"})
                return ref_def
            # 递归处理字典内的每个字段
            for key, value in obj.items():
                obj[key] = _deref(value)
        elif isinstance(obj, list):
            # 递归处理列表内的每个元素
            for idx, item in enumerate(obj):
                obj[idx] = _deref(item)
        return obj
    
    # 深拷贝原Schema避免修改原始数据
    dereferenced_schema = json.loads(json.dumps(schema))
    dereferenced_schema = _deref(dereferenced_schema)
    # 删除不再需要的$defs字段
    if "$defs" in dereferenced_schema:
        del dereferenced_schema["$defs"]
    return dereferenced_schema

# 生成并处理Schema
raw_schema = InvoiceHeader.model_json_schema()
flattened_schema = dereference_schema(raw_schema)
print(json.dumps(flattened_schema, indent=2))

运行后得到完全内嵌的Schema:

{
  "properties": {
    "invoice_number": {
      "default": "",
      "description": "The unique invoice number",
      "title": "Invoice Number",
      "type": "string"
    },
    "invoice_date": {
      "default": "",
      "description": "The date invoice was created",
      "title": "Invoice Date",
      "type": "string"
    },
    "vendor_info": {
      "default": "",
      "description": "Description of the vendor",
      "properties": {
        "vendor_name": {
          "default": "",
          "description": "Vendor Name",
          "title": "Vendor Name",
          "type": "string"
        },
        "vendor_vat_no": {
          "default": "",
          "description": "Vendor VAT Number",
          "title": "Vendor Vat No",
          "type": "string"
        }
      },
      "title": "VendorInfo",
      "type": "object"
    }
  },
  "title": "InvoiceHeader",
  "type": "object"
}

方法2:使用第三方库自动解引用

如果不想手动编写递归逻辑,可以用json-schema-ref-parser库自动处理所有引用关系。

首先安装库:

pip install json-schema-ref-parser

然后使用库的dereference方法处理Schema:

from pydantic import BaseModel, Field
import json
from jsonschema_ref_parser import dereference

class VendorInfo(BaseModel):
    vendor_name: str = Field("", description= "Vendor Name")
    vendor_vat_no: str = Field("", description= "Vendor VAT Number")

class InvoiceHeader(BaseModel):
    invoice_number: str = Field("", description= "The unique invoice number")
    invoice_date: str = Field("", description= "The date invoice was created")
    vendor_info: VendorInfo = Field("", description= "Description of the vendor")

raw_schema = InvoiceHeader.model_json_schema()
# 自动解引用所有$ref
flattened_schema = dereference(raw_schema)
# 移除残留的$defs字段
if "$defs" in flattened_schema:
    del flattened_schema["$defs"]
print(json.dumps(flattened_schema, indent=2))

这个方法适合处理复杂嵌套的Schema,无需手动维护递归逻辑。


内容的提问来源于stack exchange,提问作者Soumadeep Dutta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:34:56