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

如何为msgspec Struct属性添加注释到JSON Schema或改用Pydantic?

如何为结构体属性添加注释到JSON Schema的description字段

你期望的JSON Schema格式是合规的,description是JSON Schema标准支持的属性,用于为结构或字段添加说明文本。以下是分别基于msgspec和Pydantic的实现方案:

一、msgspec 实现方案

msgspec默认不支持提取属性的行内注释,需要通过AST解析类定义的源码,手动提取注释后修改生成的JSON Schema:

import json
import ast
import msgspec
from msgspec import Struct

def print_schema(schema):
    encoded_schema = msgspec.json.encode(schema)
    formatted_schema = json.dumps(json.loads(encoded_schema), indent=4)
    print(formatted_schema)

def get_field_comments(cls):
    """提取Struct类中属性的行内注释"""
    tree = ast.parse(open(cls.__module__.__file__).read())
    class_node = None
    for node in ast.walk(tree):
        if isinstance(node, ast.ClassDef) and node.name == cls.__name__:
            class_node = node
            break
    if not class_node:
        return {}
    
    comments = {}
    for stmt in class_node.body:
        if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
            field_name = stmt.target.id
            if stmt.end_lineno:
                with open(cls.__module__.__file__, 'r') as f:
                    lines = f.readlines()
                comment_line = lines[stmt.end_lineno - 1].strip()
                if comment_line.startswith('#'):
                    comments[field_name] = comment_line[1:].strip()
    return comments

class Product(Struct):
    """A product in a catalog"""
    id: int      # DB uid
    name: str    # Name of product
    price: float # Price of product

# 生成原始Schema并注入注释
schema = msgspec.json.schema(Product)
field_comments = get_field_comments(Product)
product_def = schema['$defs']['Product']
for field, desc in field_comments.items():
    if field in product_def['properties']:
        product_def['properties'][field]['description'] = desc

print_schema(schema)

注意:该方法依赖本地源码文件,无法在交互式环境(如Jupyter Notebook)中使用。

二、Pydantic 实现方案

Pydantic原生支持字段描述,有两种常用实现方式:

方式1:使用Field显式指定描述

这是最可靠、最符合Pydantic规范的写法:

import json
from pydantic import BaseModel, Field

class Product(BaseModel):
    """A product in a catalog"""
    id: int = Field(description="DB uid")
    name: str = Field(description="Name of product")
    price: float = Field(description="Price of product")

# 生成并打印JSON Schema
schema = Product.model_json_schema()
print(json.dumps(schema, indent=4))

方式2:自动提取行内注释作为描述

如果希望保持代码简洁,可通过AST解析自动提取注释:

import json
import ast
from pydantic import BaseModel

def set_field_descriptions(cls):
    """为BaseModel字段添加行内注释作为description"""
    tree = ast.parse(open(cls.__module__.__file__).read())
    class_node = None
    for node in ast.walk(tree):
        if isinstance(node, ast.ClassDef) and node.name == cls.__name__:
            class_node = node
            break
    if not class_node:
        return cls
    
    comments = {}
    for stmt in class_node.body:
        if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
            field_name = stmt.target.id
            if stmt.end_lineno:
                with open(cls.__module__.__file__, 'r') as f:
                    lines = f.readlines()
                comment_line = lines[stmt.end_lineno - 1].strip()
                if comment_line.startswith('#'):
                    comments[field_name] = comment_line[1:].strip()
    
    for field_name, desc in comments.items():
        if field_name in cls.model_fields:
            cls.model_fields[field_name].description = desc
    return cls

@set_field_descriptions
class Product(BaseModel):
    """A product in a catalog"""
    id: int      # DB uid
    name: str    # Name of product
    price: float # Price of product

schema = Product.model_json_schema()
print(json.dumps(schema, indent=4))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:30:09