python - Generate pydantic model from a dict - Stack Overflow
JSONtoPydantic - Generate Pydantic Models from JSON in the browser
python - Is it possible to extend pydantic models generated using datamodel-code-generator? - Stack Overflow
dynamic - Dynamically Generating Pydantic Model from a Schema JSON File - Stack Overflow
» pip install datamodel-code-generator
In Pydantic 2, you can use MyModel.model_validate(my_dict) to generate a model from a dictionary. According to the documentation –
this is very similar to the
__init__method of the model, except it takes a dict rather than keyword arguments.
If you're Pydantic 1, the method is parse_obj instead.
You can also use its __init__ method:
your_model = YourModel(**your_dict)
» pip install improved-datamodel-codegen
https://jsontopydantic.com
Hi there! I built this over the weekend and figured someone other than myself might find it useful.
Like many who work with REST APIs in Python, I've recently fallen in love with Pydantic. If you haven't heard of Pydantic, it's a data validation and parsing library that makes working with JSON in Python quite pleasant.
I needed a quick way to generate a Pydantic model from any given sample of JSON, and hacked together this application to do so. You can paste in a valid JSON string, and you'll get a valid Pydantic model back.
This is helpful if you're working with poorly documented APIs, really big objects, or have lots of edge cases to catch.
Check it out and let me know what you think!
Code -> https://github.com/brokenloop/jsontopydantic
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.
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))