diff --git a/src/datamodel_code_generator/__main__.py b/src/datamodel_code_generator/__main__.py index 43fe4028f..84e6a9bfe 100644 --- a/src/datamodel_code_generator/__main__.py +++ b/src/datamodel_code_generator/__main__.py @@ -915,8 +915,13 @@ def _serialize_python_type(tp: type) -> str | None: # noqa: PLR0911 def _simple_type_name(tp: type) -> str: """Get a simple string representation of a type.""" + from typing import get_origin # noqa: PLC0415 + if tp is type(None): return "None" + # For generic types (e.g., dict[str, Any]), use full string representation + if get_origin(tp) is not None: + return str(tp).replace("typing.", "") if hasattr(tp, "__name__"): return tp.__name__ return str(tp).replace("typing.", "") # pragma: no cover diff --git a/src/datamodel_code_generator/config.py b/src/datamodel_code_generator/config.py index b8bc22402..25635ad25 100644 --- a/src/datamodel_code_generator/config.py +++ b/src/datamodel_code_generator/config.py @@ -7,7 +7,7 @@ from pathlib import Path # noqa: TC003 - used at runtime by Pydantic from typing import TYPE_CHECKING, Annotated, Any -from pydantic import BaseModel, Field, WithJsonSchema +from pydantic import BaseModel, Field from datamodel_code_generator.enums import ( DEFAULT_SHARED_MODULE_NAME, @@ -48,10 +48,12 @@ CallableSchema = Callable[[str], str] DumpResolveReferenceAction = Callable[[Iterable[str]], str] DefaultPutDictSchema = DefaultPutDict[str, str] -ExtraTemplateDataType = Annotated[ - defaultdict[str, Annotated[dict[str, Any], Field(default_factory=dict)]], - WithJsonSchema({"type": "object", "x-python-type": "defaultdict[str, dict[str, Any]]"}), -] +if TYPE_CHECKING: + ExtraTemplateDataType = defaultdict[str, dict[str, Any]] +elif is_pydantic_v2(): + ExtraTemplateDataType = defaultdict[str, Annotated[dict[str, Any], Field(default_factory=dict)]] +else: + ExtraTemplateDataType = defaultdict[str, dict[str, Any]] class GenerateConfig(BaseModel): diff --git a/src/datamodel_code_generator/parser/jsonschema.py b/src/datamodel_code_generator/parser/jsonschema.py index 4764905f0..092c18398 100644 --- a/src/datamodel_code_generator/parser/jsonschema.py +++ b/src/datamodel_code_generator/parser/jsonschema.py @@ -629,6 +629,12 @@ class JsonSchemaParser(Parser): PYTHON_TYPE_OVERRIDE_ALWAYS: ClassVar[frozenset[str]] = frozenset({ "Callable", "Type", + # collections types that have no JSON Schema equivalent + "defaultdict", + "OrderedDict", + "Counter", + "deque", + "ChainMap", }) def __init__( # noqa: PLR0913 @@ -1399,11 +1405,16 @@ def _is_compatible_python_type(self, schema_type: str | None, python_type: str) return base_type in compatible def _extract_all_type_names(self, type_str: str) -> list[str]: # noqa: PLR6301 - """Extract all type names from a type annotation string.""" - # Match type names: word characters starting with uppercase, not preceded by a dot - # This handles cases like Callable[[Iterable[str]], str] - pattern = r"(?