📘 Generate from OpenAPI¶
Generate Pydantic models from OpenAPI 3 schema definitions.
🚀 Quick Start¶
📝 Example¶
api.yaml
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
passthroughBehavior: when_no_templates
httpMethod: POST
type: aws_proxy
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
passthroughBehavior: when_no_templates
httpMethod: POST
type: aws_proxy
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
passthroughBehavior: when_no_templates
httpMethod: POST
type: aws_proxy
components:
schemas:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
default: 1
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Users:
type: array
items:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Id:
type: string
Rules:
type: array
items:
type: string
Error:
description: error result
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
apis:
type: array
items:
type: object
properties:
apiKey:
type: string
description: To be used as a dataset parameter value
apiVersionNumber:
type: string
description: To be used as a version parameter value
apiUrl:
type: string
format: uri
description: "The URL describing the dataset's fields"
apiDocumentationUrl:
type: string
format: uri
description: A URL to the API console for each API
Event:
type: object
description: Event object
properties:
name:
type: string
Result:
type: object
properties:
event:
$ref: '#/components/schemas/Event'
✨ Generated model.py:
from __future__ import annotations
from pydantic import AnyUrl, BaseModel, Field, RootModel
class Pet(BaseModel):
id: int
name: str
tag: str | None = None
class Pets(RootModel[list[Pet]]):
root: list[Pet]
class User(BaseModel):
id: int
name: str
tag: str | None = None
class Users(RootModel[list[User]]):
root: list[User]
class Id(RootModel[str]):
root: str
class Rules(RootModel[list[str]]):
root: list[str]
class Error(BaseModel):
code: int
message: str
class Api(BaseModel):
apiKey: str | None = Field(
None, description='To be used as a dataset parameter value'
)
apiVersionNumber: str | None = Field(
None, description='To be used as a version parameter value'
)
apiUrl: AnyUrl | None = Field(
None, description="The URL describing the dataset's fields"
)
apiDocumentationUrl: AnyUrl | None = Field(
None, description='A URL to the API console for each API'
)
class Apis(RootModel[list[Api]]):
root: list[Api]
class Event(BaseModel):
name: str | None = None
class Result(BaseModel):
event: Event | None = None
📖 readOnly / writeOnly Properties¶
OpenAPI 3.x supports readOnly and writeOnly property annotations:
- 📤 readOnly: Property is only returned in responses (e.g.,
id,created_at) - 📥 writeOnly: Property is only sent in requests (e.g.,
password)
⚙️ Option: --read-only-write-only-model-type¶
This option generates separate Request/Response models based on these annotations.
| Value | Description |
|---|---|
| (not set) | Default. No special handling (backward compatible) |
request-response |
Generate only Request/Response models (no base model) |
all |
Generate base model + Request + Response models |
📋 Example Schema¶
openapi: "3.0.0"
info:
title: Read Only Write Only Test API
version: "1.0"
paths: {}
components:
schemas:
User:
type: object
required:
- id
- name
- password
properties:
id:
type: integer
readOnly: true
name:
type: string
password:
type: string
writeOnly: true
created_at:
type: string
format: date-time
readOnly: true
secret_token:
type: string
writeOnly: true
✨ Generated Output¶
datamodel-codegen --input user.yaml --input-file-type openapi \
--output-model-type pydantic_v2.BaseModel \
--read-only-write-only-model-type all
from __future__ import annotations
from pydantic import AwareDatetime, BaseModel
class UserRequest(BaseModel):
name: str
password: str
secret_token: str | None = None
class UserResponse(BaseModel):
id: int
name: str
created_at: AwareDatetime | None = None
class User(BaseModel):
id: int
name: str
password: str
created_at: AwareDatetime | None = None
secret_token: str | None = None
🎯 Usage Patterns¶
| Use Case | Recommended Option | Generated Models |
|---|---|---|
| API client validation | request-response |
UserRequest, UserResponse |
| Database ORM mapping | (not set) | User |
| Both client & ORM | all |
User, UserRequest, UserResponse |
🔗 Behavior with allOf Inheritance¶
When using allOf with $ref, fields from all referenced schemas are flattened into Request/Response models:
openapi: "3.0.0"
info:
title: Read Only Write Only AllOf Test API
version: "1.0"
paths: {}
components:
schemas:
Timestamps:
type: object
properties:
created_at:
type: string
format: date-time
readOnly: true
updated_at:
type: string
format: date-time
readOnly: true
Credentials:
type: object
properties:
password:
type: string
writeOnly: true
api_key:
type: string
writeOnly: true
User:
allOf:
- $ref: "#/components/schemas/Timestamps"
- $ref: "#/components/schemas/Credentials"
- type: object
required:
- id
- name
properties:
id:
type: integer
readOnly: true
name:
type: string
email:
type: string
Generated UserRequest will exclude created_at, updated_at, and id because they are readOnly fields from the flattened Timestamps/User schemas. Generated UserResponse will exclude password and api_key because they are writeOnly fields from Credentials.
⚠️ Collision Handling¶
If a schema named UserRequest or UserResponse already exists, the generated model will be named UserRequestModel or UserResponseModel to avoid conflicts.
📤 Supported Output Formats¶
This option works with all output formats:
pydantic_v2.BaseModelpydantic_v2.dataclassdataclasses.dataclasstyping.TypedDictmsgspec.Struct
🔗 Supported $ref Types¶
readOnly/writeOnly resolution works with local and file reference types:
| Reference Type | Example | Support |
|---|---|---|
| Local | #/components/schemas/User |
✅ Supported |
| File | ./common.yaml#/User |
✅ Supported |
📖 See Also¶
- 🖥️ CLI Reference: OpenAPI-only Options - All OpenAPI-specific CLI options
- ⚙️ CLI Reference: Base Options - Input/output configuration options