Skip to content

Commit f4b240a

Browse files
authored
Document external library import use case for --type-overrides (#2893)
1 parent 4f26e46 commit f4b240a

4 files changed

Lines changed: 124 additions & 1 deletion

File tree

docs/cli-reference/typing-customization.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,6 +2736,25 @@ The `--type-mappings` flag configures the code generation behavior.
27362736

27372737
Replace schema model types with custom Python types via JSON mapping.
27382738

2739+
This option is useful for importing models from external libraries (like `geojson-pydantic`)
2740+
instead of generating them.
2741+
2742+
**Override Formats:**
2743+
2744+
| Format | Description |
2745+
|--------|-------------|
2746+
| `{"ModelName": "package.Type"}` | Model-level: Skip generating `ModelName` and import from `package` |
2747+
| `{"Model.field": "package.Type"}` | Scoped: Override only specific field in specific model |
2748+
2749+
**Common Use Cases:**
2750+
2751+
| Use Case | Example Override |
2752+
|----------|------------------|
2753+
| GeoJSON types | `{"Feature": "geojson_pydantic.Feature"}` |
2754+
| Custom datetime | `{"Timestamp": "pendulum.DateTime"}` |
2755+
| MongoDB ObjectId | `{"ObjectId": "bson.ObjectId"}` |
2756+
| Custom validators | `{"Email": "my_app.types.ValidatedEmail"}` |
2757+
27392758
!!! tip "Usage"
27402759

27412760
```bash
@@ -2744,6 +2763,11 @@ Replace schema model types with custom Python types via JSON mapping.
27442763

27452764
1. :material-arrow-left: `--type-overrides` - the option documented here
27462765

2766+
!!! note "Model-level overrides skip generation"
2767+
When you specify a model-level override (without a dot in the key), the generator will
2768+
**skip generating that model entirely** and import it from the specified package instead.
2769+
2770+
27472771
??? example "Examples"
27482772

27492773
**Input Schema:**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# generated by datamodel-codegen:
2+
# filename: type_overrides_external_lib.json
3+
# timestamp: 1985-10-26T08:21:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from typing import Any
8+
9+
from geojson_pydantic import Feature, FeatureCollection
10+
from pydantic import BaseModel
11+
12+
13+
class Model(BaseModel):
14+
__root__: Any
15+
16+
17+
class Place(BaseModel):
18+
name: str | None = None
19+
location: Feature | None = None
20+
boundary: FeatureCollection | None = None
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"definitions": {
4+
"Feature": {
5+
"type": "object",
6+
"properties": {
7+
"type": {"type": "string"},
8+
"geometry": {"type": "object"}
9+
}
10+
},
11+
"FeatureCollection": {
12+
"type": "object",
13+
"properties": {
14+
"type": {"type": "string"},
15+
"features": {
16+
"type": "array",
17+
"items": {"$ref": "#/definitions/Feature"}
18+
}
19+
}
20+
},
21+
"Place": {
22+
"type": "object",
23+
"properties": {
24+
"name": {"type": "string"},
25+
"location": {"$ref": "#/definitions/Feature"},
26+
"boundary": {"$ref": "#/definitions/FeatureCollection"}
27+
}
28+
}
29+
}
30+
}

tests/main/test_main_general.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,31 @@ def test_dataclass_arguments_invalid(json_str: str, match: str) -> None:
674674

675675
@pytest.mark.cli_doc(
676676
options=["--type-overrides"],
677-
option_description="""Replace schema model types with custom Python types via JSON mapping.""",
677+
option_description="""Replace schema model types with custom Python types via JSON mapping.
678+
679+
This option is useful for importing models from external libraries (like `geojson-pydantic`)
680+
instead of generating them.
681+
682+
**Override Formats:**
683+
684+
| Format | Description |
685+
|--------|-------------|
686+
| `{"ModelName": "package.Type"}` | Model-level: Skip generating `ModelName` and import from `package` |
687+
| `{"Model.field": "package.Type"}` | Scoped: Override only specific field in specific model |
688+
689+
!!! note "Model-level overrides skip generation"
690+
When you specify a model-level override (without a dot in the key), the generator will
691+
**skip generating that model entirely** and import it from the specified package instead.
692+
693+
**Common Use Cases:**
694+
695+
| Use Case | Example Override |
696+
|----------|------------------|
697+
| GeoJSON types | `{"Feature": "geojson_pydantic.Feature"}` |
698+
| Custom datetime | `{"Timestamp": "pendulum.DateTime"}` |
699+
| MongoDB ObjectId | `{"ObjectId": "bson.ObjectId"}` |
700+
| Custom validators | `{"Email": "my_app.types.ValidatedEmail"}` |
701+
""",
678702
input_schema="jsonschema/type_overrides_test.json",
679703
cli_args=["--type-overrides", '{"CustomType": "my_app.types.CustomType"}'],
680704
golden_output="main/type_overrides_model_level.py",
@@ -695,6 +719,31 @@ def test_type_overrides_model_level(output_file: Path) -> None:
695719
)
696720

697721

722+
@pytest.mark.cli_doc(
723+
options=["--type-overrides"],
724+
option_description="""Replace schema model types with custom Python types via JSON mapping.""",
725+
input_schema="jsonschema/type_overrides_external_lib.json",
726+
cli_args=[
727+
"--type-overrides",
728+
'{"Feature": "geojson_pydantic.Feature", "FeatureCollection": "geojson_pydantic.FeatureCollection"}',
729+
],
730+
golden_output="main/type_overrides_external_lib.py",
731+
)
732+
@freeze_time(TIMESTAMP)
733+
def test_type_overrides_external_lib(output_file: Path) -> None:
734+
"""Test --type-overrides with external library types like geojson-pydantic."""
735+
run_main_and_assert(
736+
input_path=JSON_SCHEMA_DATA_PATH / "type_overrides_external_lib.json",
737+
output_path=output_file,
738+
input_file_type="jsonschema",
739+
assert_func=assert_file_content,
740+
extra_args=[
741+
"--type-overrides",
742+
'{"Feature": "geojson_pydantic.Feature", "FeatureCollection": "geojson_pydantic.FeatureCollection"}',
743+
],
744+
)
745+
746+
698747
@freeze_time(TIMESTAMP)
699748
def test_type_overrides_scoped(output_file: Path) -> None:
700749
"""Test --type-overrides with scoped override replaces specific field only."""

0 commit comments

Comments
 (0)