from pydantic import BaseModel from typing import get_origin, get_args, List, Dict, Optional, Union from datetime import datetime def pydantic_to_template(model: type[BaseModel]): """ Recursively converts a pydantic model class into a minimal JSON template (dict). """ fields = {} for name, field in model.model_fields.items(): fields[name] = type_to_template(field.annotation) return fields def type_to_template(annotation): origin = get_origin(annotation) # Optional[T] / Union[T, None] -> T # Handles both typing.Optional[T] and the newer `T | None` syntax if origin is Union: args = [arg for arg in get_args(annotation) if arg is not type(None)] if len(args) == 1: annotation = args[0] origin = get_origin(annotation) # List[T] if origin is list or origin is List: inner = get_args(annotation)[0] return [type_to_template(inner)] # Dict[str, T] if origin is dict or origin is Dict: inner = get_args(annotation)[1] return {"string": type_to_template(inner)} # Pydantic model if isinstance(annotation, type) and issubclass(annotation, BaseModel): return pydantic_to_template(annotation) # Primitive types if annotation in [str, int, float]: if annotation is str: return "string" if annotation is int: return 'int' if annotation is float: return 'float' # datetime if annotation is datetime: return 'datetime' # Fallback return 'any'