I’ll attempt to answer your questions about the .parse() version of chat completions, found in ‘beta’. The new beta method, when used with a BaseModel, enforces and passes strict:true without regard to your desires otherwise when you use a pydantic BaseModel as the response_format. For example, le… Answer from arata on community.openai.com
🌐
Pydantic
docs.pydantic.dev › 1.10 › usage › schema
Schema - Pydantic
The callable is expected to mutate the schema dictionary in-place; the return value is not used. For example, the title key can be removed from the model's properties: ... from typing import Dict, Any, Type from pydantic import BaseModel class Person(BaseModel): name: str age: int class Config: @staticmethod def schema_extra(schema: Dict[str, Any], model: Type['Person']) -> None: for prop in schema.get('properties', {}).values(): prop.pop('title', None) print(Person.schema_json(indent=2))
🌐
Pydantic
docs.pydantic.dev › latest › concepts › json_schema
JSON Schema - Pydantic Validation
By default, Pydantic recursively sorts JSON schemas by alphabetically sorting keys. Notably, Pydantic skips sorting the values of the properties key, to preserve the order of the fields as they were defined in the model. If you would like to customize this behavior, you can override the sort method in your custom GenerateJsonSchema subclass. The below example uses a no-op sort method to disable sorting entirely, which is reflected in the preserved order of the model fields and json_schema_extra keys:
🌐
Pydantic
docs.pydantic.dev › latest › examples › orms
Databases - Pydantic Validation
import sqlalchemy as sa from sqlalchemy.orm import declarative_base from pydantic import BaseModel, ConfigDict, Field class MyModel(BaseModel): model_config = ConfigDict(from_attributes=True) metadata: dict[str, str] = Field(alias='metadata_') Base = declarative_base() class MyTableModel(Base): __tablename__ = 'my_table' id = sa.Column('id', sa.Integer, primary_key=True) # 'metadata' is reserved by SQLAlchemy, hence the '_' metadata_ = sa.Column('metadata', sa.JSON) sql_model = MyTableModel(metadata_={'key': 'val'}, id=1) pydantic_model = MyModel.model_validate(sql_model) print(pydantic_model.model_dump()) #> {'metadata': {'key': 'val'}} print(pydantic_model.model_dump(by_alias=True)) #> {'metadata_': {'key': 'val'}} ... The example above works because aliases have priority over field names for field population.
🌐
Pydantic
docs.pydantic.dev › latest
Welcome to Pydantic - Pydantic Validation
To see Pydantic at work, let's start with a simple example, creating a custom class that inherits from BaseModel:
🌐
DataCamp
datacamp.com › tutorial › pydantic
Pydantic: A Guide With Practical Examples | DataCamp
June 25, 2025 - Each Field() parameter serves a specific purpose: min_length and max_length prevent database schema violations, gt and le create business logic boundaries, and pattern validates formatted data using regular expressions. The Field(...) syntax with ellipsis marks the required fields, while Field(None, ...) creates optional fields with validation rules. By default, Pydantic converts compatible types rather than rejecting them outright.
🌐
YouTube
youtube.com › watch
Python FastAPI Tutorial (Part 4): Pydantic Schemas - Request and Response Validation - YouTube
In this Python FastAPI tutorial, we'll be learning how to use Pydantic schemas to validate API requests and responses in FastAPI. We'll create a schemas file...
Published   January 12, 2026
Top answer
1 of 5
11

This has been discussed some time ago and Samuel Colvin said he didn't want to pursue this as a feature for Pydantic.

If you are fine with code generation instead of actual runtime creation of models, you can use the datamodel-code-generator.

To be honest, I struggle to see the use case for generating complex models at runtime, seeing as their main purpose is validation, implying that you think about correct schema before running your program. But that is just my view.

For simple models I guess you can throw together your own logic for this fairly quickly.

If do you need something more sophisticated, the aforementioned library does offer some extensibility. You should be able to import and inherit from some of their classes like the JsonSchemaParser. Maybe that will get you somewhere.

Ultimately I think this becomes non-trivial very quickly, which is why Pydantic's maintainer didn't want to deal with it and why there is a whole separate project for this.

2 of 5
7

Updated @Alon's answer to handle nested modals:

from typing import Any, Type, Optional
from enum import Enum

from pydantic import BaseModel, Field, create_model


def json_schema_to_base_model(schema: dict[str, Any]) -> Type[BaseModel]:
    type_mapping: dict[str, type] = {
        "string": str,
        "integer": int,
        "number": float,
        "boolean": bool,
        "array": list,
        "object": dict,
    }

    properties = schema.get("properties", {})
    required_fields = schema.get("required", [])
    model_fields = {}

    def process_field(field_name: str, field_props: dict[str, Any]) -> tuple:
        """Recursively processes a field and returns its type and Field instance."""
        json_type = field_props.get("type", "string")
        enum_values = field_props.get("enum")

        # Handle Enums
        if enum_values:
            enum_name: str = f"{field_name.capitalize()}Enum"
            field_type = Enum(enum_name, {v: v for v in enum_values})
        # Handle Nested Objects
        elif json_type == "object" and "properties" in field_props:
            field_type = json_schema_to_base_model(
                field_props
            )  # Recursively create submodel
        # Handle Arrays with Nested Objects
        elif json_type == "array" and "items" in field_props:
            item_props = field_props["items"]
            if item_props.get("type") == "object":
                item_type: type[BaseModel] = json_schema_to_base_model(item_props)
            else:
                item_type: type = type_mapping.get(item_props.get("type"), Any)
            field_type = list[item_type]
        else:
            field_type = type_mapping.get(json_type, Any)

        # Handle default values and optionality
        default_value = field_props.get("default", ...)
        nullable = field_props.get("nullable", False)
        description = field_props.get("title", "")

        if nullable:
            field_type = Optional[field_type]

        if field_name not in required_fields:
            default_value = field_props.get("default", None)

        return field_type, Field(default_value, description=description)

    # Process each field
    for field_name, field_props in properties.items():
        model_fields[field_name] = process_field(field_name, field_props)

    return create_model(schema.get("title", "DynamicModel"), **model_fields)

Example Schema

schema = {
    "title": "User",
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
        "is_active": {"type": "boolean"},
        "address": {
            "type": "object",
            "properties": {
                "street": {"type": "string"},
                "city": {"type": "string"},
                "zipcode": {"type": "integer"},
            },
        },
        "roles": {
            "type": "array",
            "items": {
                "type": "string",
                "enum": ["admin", "user", "guest"]
            }
        }
    },
    "required": ["name", "age"]
}

Generate the Pydantic model

DynamicModel = json_schema_to_base_model(schema)

Example usage

print(DynamicModel.schema_json(indent=2))
Find elsewhere
🌐
Medium
medium.com › @kishanbabariya101 › episode-8-json-schema-generation-in-pydantic-9a4c4fee02c8
Episode 8: JSON Schema Generation in Pydantic | by Kishan Babariya | Medium
December 17, 2024 - The model_json_schema() method generates the JSON Schema for a model. ... Field names, types, and constraints. Default values and required fields. FastAPI uses Pydantic’s JSON Schema generation to create interactive API documentation via Swagger UI and ReDoc.
🌐
Pydantic
pydantic.dev › articles › llm-intro
How to Use Pydantic for LLMs: Schema, Validation & Prompts
January 4, 2024 - Now, notice in this example that the prompts we use contain purely the data we want, where the tools and tool_choice now capture the schemas we want to output. This separation of concerns makes it much easier to organize the 'data' and the 'description' of the data that we want back out. from typing import List from pydantic import BaseModel from openai import OpenAI client = OpenAI() class PythonPackage(BaseModel): name: str author: str class Packages(BaseModel): packages: List[PythonPackage] resp = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ { "role": "user", "content":
🌐
Pydantic
docs.pydantic.dev › latest › internals › architecture
Architecture - Pydantic Validation
In the case of a Pydantic model, a core schema will be constructed and set as the __pydantic_core_schema__ attribute. To illustrate what a core schema looks like, we will take the example of the bool core schema:
🌐
FastAPI
fastapi.tiangolo.com › tutorial › schema-extra-example
Declare Request Example Data - FastAPI
Even after OpenAPI 3.1.0 was released ... examples inside a Pydantic model, using schema_extra or Field(examples=["something"]) that example is added to the JSON Schema for that Pydantic model....
🌐
Medium
medium.com › @overfittedcat › the-configuration-schema-using-pydantic-5b752968832e
The configuration schema using Pydantic | by Overfitted Cat | Medium
July 13, 2022 - You can find more information and features https://pydantic-docs.helpmanual.io/usage/settings/. For now, let’s focus on our use case on polymorphic settings structure and how we can use Pydantic here. We have a class, AppSettings, which denotes the global configuration class containing configuration for all components, for example.
🌐
GitHub
github.com › pydantic › pydantic › blob › main › pydantic › v1 › schema.py
pydantic/pydantic/v1/schema.py at main · pydantic/pydantic
:param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema · :param field_name: name of the field for use in error messages · :param validate_assignment: default False, flag for BaseModel Config value of validate_assignment · :return: the same ``annotation`` if unmodified or a new annotation with validation in place ... f'\nFor more details see https://docs.pydantic.dev/usage/schema/#unenforced-field-constraints'
Author   pydantic
🌐
Netlify
field-idempotency--pydantic-docs.netlify.app › usage › schema
Schema - pydantic
If you want to force the constraint to appear in the schema, even though it's not being checked upon parsing, you can use variadic arguments to Field() with the raw schema attribute name: from pydantic import BaseModel, Field, PositiveInt try: # this won't work since PositiveInt takes precedence over the # constraints defined in Field meaning they're ignored class Model(BaseModel): foo: PositiveInt = Field(..., lt=10) except ValueError as e: print(e) """ On field "foo" the following field constraints are set but not enforced: lt.
🌐
Pydantic
docs.pydantic.dev › 2.4 › concepts › json_schema
JSON Schema - Pydantic
The generated JSON schemas are compliant with the following specifications: ... OpenAPI extensions. import json from enum import Enum from typing import Union from typing_extensions import Annotated from pydantic import BaseModel, Field from pydantic.config import ConfigDict class FooBar(BaseModel): count: int size: Union[float, None] = None class Gender(str, Enum): male = 'male' female = 'female' other = 'other' not_given = 'not_given' class MainModel(BaseModel): """ This is the description of the main model """ model_config = ConfigDict(title='Main') foo_bar: FooBar gender: Annotated[Union[Gender, None], Field(alias='Gender')] = None snap: int = Field( 42, title='The Snap', description='this is the value of snap', gt=30, lt=50, ) print(json.dumps(MainModel.model_json_schema(), indent=2))
🌐
Pydantic
docs.pydantic.dev › latest › concepts › models
Models - Pydantic Validation
When you define a model class in your code, Pydantic will analyze the body of the class to collect a variety of information required to perform validation and serialization, gathered in a core schema. Notably, the model's type annotations are evaluated to understand the valid types for each field (more information can be found in the Architecture documentation).
🌐
Orchestra
getorchestra.io › guides › pydantic-json-schema-a-comprehensive-guide-for-fastapi-users
Pydantic JSON Schema: A Comprehensive Guide for FastAPI Users | Orchestra
April 8, 2024 - In this example, we have an Address model nested within the UserWithAddress model. Generating the schema for UserWithAddress will include the structure of the Address model. In FastAPI, these schemas are used automatically for documentation ...
🌐
Pydantic
docs.pydantic.dev › latest › api › pydantic_core_schema
pydantic_core.core_schema - Pydantic Validation
Returns a schema that matches an enum value, e.g.: from enum import Enum from pydantic_core import SchemaValidator, core_schema class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 schema = core_schema.enum_schema(Color, list(Color.__members__.values())) ...