Pydantic crée des schémas de modèles imbriqués à l'aide de $ref
dans les propriétés définies dans d'autres modèles. Le schéma aura alors, par défaut, un fichier definitions
contenant les schémas qui y sont référencés.
Dans votre cas particulier, le Log
ressemblerait à ceci :
{
"title": "Log",
"type": "object",
"properties": {
"user": {
"title": "User",
"anyOf": [
{
"$ref": "#/definitions/Admin"
},
{
"$ref": "#/definitions/SimpleUser"
}
]
}
},
"definitions": {
"Admin": {
"title": "Admin",
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
}
},
"required": [
"name"
]
},
"SimpleUser": {
"title": "SimpleUser",
"type": "object",
"properties": {
"age": {
"title": "Age",
"type": "integer"
}
},
"required": [
"age"
]
}
}
}
L'union se reflète dans la anyOf
chaque objet du tableau faisant référence à l'un des modèles.
D'après ce que j'ai compris de la spécification actuelle du schéma JSON, vous êtes autorisé à ajouter d'autres mots clés aux côtés de $ref
. Je suppose donc que vous pouvez communiquer que SimpleUser
est une option obsolète pour user
en ajoutant simplement l'élément deprecated
à côté de la référence au SimpleUser
définition.
Pydantic vous permet de contrôler la façon dont le schéma JSON est construit grâce à l'option schema_extra
paramètre de configuration. Si vous le définissez comme une méthode statique de la méthode interne Config
vous pouvez la modifier à votre guise.
La mise en œuvre de cet ajout pourrait donc se faire de la manière suivante :
from typing import Any
from pydantic import BaseModel, Field
class Admin(BaseModel):
name: str
class SimpleUser(BaseModel):
age: int
class Log(BaseModel):
user: Admin | SimpleUser | None = Field(default=None)
class Config:
@staticmethod
def schema_extra(schema: dict[str, Any]) -> None:
"""Marks the `SimpleUser` option for `user` as deprecated."""
user_property = schema["properties"]["user"]
for obj in user_property["anyOf"]:
ref = obj.get("$ref")
if isinstance(ref, str) and ref.endswith("/SimpleUser"):
obj["deprecated"] = True
break
La sortie de print(Log.schema_json(indent=2))
maintenant :
{
"title": "Log",
"type": "object",
"properties": {
"user": {
"title": "User",
"anyOf": [
{
"$ref": "#/definitions/Admin"
},
{
"$ref": "#/definitions/SimpleUser",
"deprecated": true
}
]
}
},
"definitions": {
"Admin": {
"title": "Admin",
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
}
},
"required": [
"name"
]
},
"SimpleUser": {
"title": "SimpleUser",
"type": "object",
"properties": {
"age": {
"title": "Age",
"type": "integer"
}
},
"required": [
"age"
]
}
}
}
La seule différence par rapport à la précédente est l'ajout de "deprecated": true
.
Je ne suis pas sûr à 100 % que ce schéma soit compris par les clients de la façon dont vous l'entendez, car je n'ai trouvé aucun exemple d'utilisation de cette façon, mais je n'ai pas non plus trouvé d'indication contraire et je pense que ce schéma est conforme à la spécification. Peut-être que quelqu'un ayant plus d'expérience avec JSON Schema peut commenter ceci pour (dis-)confirmer.
PS :
Si les propriétés additionnelles à côté de la $ref
sont ignorées par le client parce qu'il s'en tient à l'option OpenAPI 3.1 vous pouvez toujours définir la propriété dépréciée sur l'ensemble de l'élément SimpleUser
modèle :
from pydantic import BaseModel, Field
class Admin(BaseModel):
name: str
class SimpleUser(BaseModel):
age: int
class Config:
schema_extra = {"deprecated": True}
class Log(BaseModel):
user: Admin | SimpleUser | None = Field(default=None)