Я использую Pydantic 2.6.4 для создания схем JSON. Если я пишу атрибут в модели Pydantic, у которого нет значения «заголовок» в его FieldInfo, Pydantic всегда будет автоматически генерировать его на основе имени атрибута при переводе модели в схему JSON. Как мне это предотвратить?
Рассмотрим следующую модель Пидантика:
class Model(BaseModel):
a: int
Результатом print(json.dumps(Model.model_json_schema())
будет:
{
"properties": {
"a": {
"title": "A",
"type": "integer"
}
},
"title": "Model",
"type": "object"
}
Обратите внимание, что для атрибута a не указан Field(title = "A")
. Pydantic генерирует это автоматически. Как заставить Pydantic выводить:
{
"properties": {
"a": {
"type": "integer"
}
},
"title": "Model",
"type": "object"
}
У Pydantic v1 было довольно сложное решение. Вам пришлось перезаписать schema_extra
в подклассе Config
следующим образом:
class Model(BaseModel):
a: int
class Config:
@staticmethod
def schema_extra(schema: dict[str, Any], model: type['Model']) -> None:
for prop in schema.get('properties', {}).values():
prop.pop('title', None)
Однако в документации Pydantic v2 говорится, что Config
устарел. Какое решение для Pydantic v2?
Спасибо!
Покопавшись немного глубже в коде pydantic, я нашел небольшой приятный способ предотвратить это. В field_title_should_be_set(...)
есть метод GenerateJsonSchema
, который можно разделить на подклассы и передать в model_json_schema(...)
.
Я не уверен, что способ, которым я перезаписал метод, достаточен для каждого крайнего случая, но, по крайней мере, для этого небольшого тестового класса он работает так, как задумано.
from pydantic import BaseModel
from pydantic._internal._core_utils import is_core_schema, CoreSchemaOrField
from pydantic.json_schema import GenerateJsonSchema
class Test(BaseModel):
a: int
class GenerateJsonSchemaWithoutDefaultTitles(GenerateJsonSchema):
def field_title_should_be_set(self, schema: CoreSchemaOrField) -> bool:
return_value = super().field_title_should_be_set(schema)
if return_value and is_core_schema(schema):
return False
return return_value
json_schema = Test.model_json_schema(schema_generator=GenerateJsonSchemaWithoutDefaultTitles)
assert "title" not in json_schema["properties"]["a"]
Вы можете сделать это с помощью Pydantic v2 следующим образом:
from pydantic import BaseModel, ConfigDict
def my_schema_extra(schema: dict[str, Any]) -> None:
for prop in schema.get('properties', {}).values():
prop.pop('title', None)
class Model(BaseModel):
a: int
model_config = ConfigDict(
json_schema_extra=my_schema_extra,
)
print(Model.schema_json())
Проблема в том, что, и мне следовало бы более четко объяснить, чего я хочу в своем вопросе, он удалит «заголовок» из всех свойств, даже из тех, для которых я указываю его в своем классе Pydantic. Это пример прямо из документации Pydantic для версии 1, но на самом деле он все равно не делает то, что я хочу, потому что я хочу иметь возможность присвоить заголовок полю, если захочу.
Пока работает и позволяет мне указать заголовок, используя Field(title = ""), если я хочу, чтобы он был! Спасибо!