如何从Python类自动生成支持继承特性的JSON Schema规范
解决方案
现有成熟库推荐
直接用Pydantic即可,它原生支持类继承场景下的JSON Schema自动生成、参数校验,完全匹配你的需求:
- 自动继承父类的字段定义、描述信息,无需手动复制
- 可灵活排除父类中不需要对外暴露的字段
- 支持直接设置字段默认值,默认值会自动同步到Schema和校验逻辑
- 调用
model_json_schema()方法即可直接生成符合规范的JSON Schema结构
Pydantic实现示例
from pydantic import BaseModel, Field class Agent(BaseModel): agent_id: str = Field(description="unique identifier") network: str = Field(description="road network used by the agent to move") origin: int = Field(description="origin position id") icon: str = Field(description="display icon") def move(self, position): self.position = position class User(Agent): # 排除父类的network字段,固定默认值为walk,不会出现在生成的Schema中 network: str = Field(default="walk", exclude=True) destination: int = Field(description="destination position id") icon: str = Field(default="user") class Vehicle(Agent): seats: int = Field(description="capacity of the vehicle") class Bike(Vehicle): network: str = Field(default="bike", exclude=True) seats: int = Field(default=1, exclude=True) icon: str = Field(default="bike") class Car(Vehicle): network: str = Field(default="drive", exclude=True) icon: str = Field(default="car") # 生成User类的JSON Schema print(User.model_json_schema())
运行上述代码生成的User类Schema会自动过滤掉network字段,required列表也会同步更新为["agent_id", "origin", "destination", "icon"],和你预期的完全一致。
自定义实现思路
如果不想引入第三方依赖,可以通过基类类方法+子类配置项的方式实现,核心逻辑如下:
- 在基础Agent类中实现
generate_schema类方法 - 子类可以定义三个配置类属性:
ADD_PROPERTIES:需要新增的字段SchemaREMOVE_PROPERTIES:需要从父类Schema中移除的字段名列表ADD_REQUIRED:新增的必填字段列表,无需重复填写父类已有的必填字段
generate_schema方法逻辑:- 递归获取所有父类的Schema
- 移除
REMOVE_PROPERTIES中指定的字段,同时同步更新required列表 - 合并
ADD_PROPERTIES中的新增字段 - 输出最终的Schema结构
简易自定义实现示例
class Agent: SCHEMA = { "properties": { "agent_id": {"type": "string", "description": "unique identifier"}, "network": {"type": "string", "description": "road network used by the agent to move"}, "origin": {"type": "integer", "description": "origin position id"}, "icon": {"type": "string", "description": "display icon"} }, "required": ["agent_id", "network", "origin", "icon"] } @classmethod def get_schema(cls): # 缓存生成的schema避免重复计算 if not hasattr(cls, '_cached_schema'): parent_schema = {} # 递归获取父类schema for base in reversed(cls.__bases__): if hasattr(base, 'get_schema'): parent_schema = base.get_schema().copy() # 处理要移除的字段 remove = getattr(cls, 'REMOVE_PROPERTIES', []) parent_schema['properties'] = {k:v for k,v in parent_schema.get('properties', {}).items() if k not in remove} parent_schema['required'] = [k for k in parent_schema.get('required', []) if k not in remove] # 合并新增字段 add_props = getattr(cls, 'ADD_PROPERTIES', {}) parent_schema['properties'].update(add_props) # 合并新增必填字段 add_required = getattr(cls, 'ADD_REQUIRED', []) parent_schema['required'] = list(set(parent_schema['required'] + add_required)) cls._cached_schema = parent_schema return cls._cached_schema class User(Agent): REMOVE_PROPERTIES = ["network"] ADD_PROPERTIES = { "destination": {"type": "integer", "description": "destination position id"} } ADD_REQUIRED = ["destination"] def __init__(self, agent_id, origin, destination, icon="user"): super().__init__(agent_id, "walk", origin, icon) self.destination = destination
调用User.get_schema()即可得到预期的Schema结构,后续新增子类只需要配置对应属性即可,无需重复写公共字段的Schema。
内容的提问来源于stack exchange,提问作者LeoDebTellae
相关产品推荐
相关产品推荐

