Code Generation with datamodel-code-generator
The datamodel-code-generator project is a library and command-line utility to generate pydantic models from just about any data source, including:
- OpenAPI 3 (YAML/JSON)
- JSON Schema
- JSON/YAML/CSV Data (which will be converted to JSON Schema)
- Python dictionary (which will be converted to JSON Schema)
- GraphQL schema
Whenever you find yourself with any data convertible JSON but without pydantic models, this tool will allow you to generate type-safe model hierarchies on demand.
pip install datamodel-code-generator
In this case, datamodel-code-generator creates pydantic models from a JSON Schema file.
datamodel-codegen --input person.json --input-file-type jsonschema --output model.py
person.json:
{
"$id": "person.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person",
"type": "object",
"properties": {
"first_name": {
"type": "string",
"description": "The person's first name."
},
"last_name": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years.",
"type": "integer",
"minimum": 0
},
"pets": {
"type": "array",
"items": [
{
"$ref": "#/definitions/Pet"
}
]
},
"comment": {
"type": "null"
}
},
"required": [
"first_name",
"last_name"
],
"definitions": {
"Pet": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
}
}
}
}
model.py:
# generated by datamodel-codegen:
# filename: person.json
# timestamp: 2020-05-19T15:07:31+00:00
from __future__ import annotations
from typing import Any
from pydantic import BaseModel, Field, conint
class Pet(BaseModel):
name: str | None = None
age: int | None = None
class Person(BaseModel):
first_name: str = Field(description="The person's first name.")
last_name: str = Field(description="The person's last name.")
age: conint(ge=0) | None = Field(None, description='Age in years.')
pets: list[Pet] | None = None
comment: Any | None = None
More information can be found on the official documentation.
A model generated from an OpenAPI or JSON Schema document is a snapshot of that contract. When the
upstream data stops matching it (a field changes type, a new required field appears), the mismatch
surfaces as a ValidationError at runtime, often the first sign the
source has drifted from the schema you generated against.
If you record validations with Logfire, those failures are stored with the payload that caused them, so you can see what changed and when it started, useful when you don’t own the schema and can’t regenerate the models until you know what moved.