Skip to content

Commit 4c3c9e9

Browse files
authored
Add --schema-version and --schema-version-mode CLI options (#2932)
* Add --jsonschema-version and --openapi-version CLI options * Add --schema-version and --schema-version-mode CLI options * Regenerate CLI docs * Add schema version strict mode warnings (#2936) * Add version-specific schema processing using schema_features * Implement flag-based behavior control for schema version * Add comprehensive version-specific feature checks with exclusive_as_number flag * Add supported formats docs and fix empty dict handling in version detection * Move Discriminator class to _openapi_types.py to avoid circular imports * Add Strict mode warnings for OpenAPI-only features in JsonSchema * Update docs with complete Strict mode warning table * Add detailed specification links to docs * Add e2e tests for schema version strict mode warnings * Regenerate CLI docs for schema-version-mode * Add unit tests for boolean schema and non-dict raw value coverage * Refactor: use direct config attribute access instead of getattr
1 parent eb92c8f commit 4c3c9e9

40 files changed

Lines changed: 1781 additions & 40 deletions

docs/cli-reference/base-options.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
| [`--input-model`](#input-model) | Import a Python type or dict schema from a module. |
1111
| [`--input-model-ref-strategy`](#input-model-ref-strategy) | Strategy for referenced types when using --input-model. |
1212
| [`--output`](#output) | Specify the destination path for generated Python code. |
13+
| [`--schema-version`](#schema-version) | Schema version to use for parsing. |
14+
| [`--schema-version-mode`](#schema-version-mode) | Schema version validation mode (strict: warn on OpenAPI exte... |
1315
| [`--url`](#url) | Fetch schema from URL with custom HTTP headers. |
1416

1517
---
@@ -326,6 +328,146 @@ is written to stdout.
326328

327329
---
328330

331+
## `--schema-version` {#schema-version}
332+
333+
Schema version to use for parsing.
334+
335+
The `--schema-version` option specifies the schema version to use instead of auto-detection.
336+
Valid values depend on input type: JsonSchema (draft-04, draft-06, draft-07, 2019-09, 2020-12)
337+
or OpenAPI (3.0, 3.1). Default is 'auto' (detected from $schema or openapi field).
338+
339+
!!! tip "Usage"
340+
341+
```bash
342+
datamodel-codegen --input schema.json --schema-version draft-07 # (1)!
343+
```
344+
345+
1. :material-arrow-left: `--schema-version` - the option documented here
346+
347+
??? example "Examples"
348+
349+
**Input Schema:**
350+
351+
```json
352+
{
353+
"$schema": "http://json-schema.org/draft-07/schema",
354+
"type": "object",
355+
"properties": {"s": {"type": ["string"]}},
356+
"required": ["s"]
357+
}
358+
```
359+
360+
**Output:**
361+
362+
> **Error:** File not found: jsonschema/simple_string.py
363+
364+
---
365+
366+
## `--schema-version-mode` {#schema-version-mode}
367+
368+
Schema version validation mode (strict: warn on OpenAPI extensions).
369+
370+
The `--schema-version-mode strict` option warns when OpenAPI-only features like
371+
`nullable` keyword are used in pure JSON Schema.
372+
373+
!!! tip "Usage"
374+
375+
```bash
376+
datamodel-codegen --input schema.json --schema-version-mode strict --output-model-type pydantic_v2.BaseModel # (1)!
377+
```
378+
379+
1. :material-arrow-left: `--schema-version-mode` - the option documented here
380+
381+
??? example "Examples"
382+
383+
=== "OpenAPI"
384+
385+
**Input Schema:**
386+
387+
```yaml
388+
openapi: "3.0.3"
389+
info:
390+
title: NullTypeTest
391+
version: "1.0"
392+
paths: {}
393+
components:
394+
schemas:
395+
Root:
396+
type: object
397+
properties:
398+
item:
399+
$ref: "#/components/schemas/NullableItem"
400+
NullableItem:
401+
type:
402+
- string
403+
- "null"
404+
```
405+
406+
**Output:**
407+
408+
```python
409+
# generated by datamodel-codegen:
410+
# filename: schema_version_strict_null_in_type_3_0.yaml
411+
# timestamp: 2019-07-26T00:00:00+00:00
412+
413+
from __future__ import annotations
414+
415+
from pydantic import BaseModel, RootModel
416+
417+
418+
class NullableItem(RootModel[str | None]):
419+
root: str | None
420+
421+
422+
class Root(BaseModel):
423+
item: NullableItem | None = None
424+
```
425+
426+
=== "JSON Schema"
427+
428+
**Input Schema:**
429+
430+
```json
431+
{
432+
"$schema": "http://json-schema.org/draft-07/schema#",
433+
"title": "Root",
434+
"type": "object",
435+
"properties": {
436+
"item": {
437+
"$ref": "#/definitions/NullableString"
438+
}
439+
},
440+
"definitions": {
441+
"NullableString": {
442+
"type": "string",
443+
"nullable": true
444+
}
445+
}
446+
}
447+
```
448+
449+
**Output:**
450+
451+
```python
452+
# generated by datamodel-codegen:
453+
# filename: schema_version_strict_nullable.json
454+
# timestamp: 2019-07-26T00:00:00+00:00
455+
456+
from __future__ import annotations
457+
458+
from pydantic import BaseModel, RootModel
459+
460+
461+
class NullableString(RootModel[str | None]):
462+
root: str | None = None
463+
464+
465+
class Root(BaseModel):
466+
item: NullableString | None = None
467+
```
468+
469+
---
470+
329471
## `--url` {#url}
330472

331473
Fetch schema from URL with custom HTTP headers.

docs/cli-reference/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This documentation is auto-generated from test cases.
88

99
| Category | Options | Description |
1010
|----------|---------|-------------|
11-
| 📁 [Base Options](base-options.md) | 7 | Input/output configuration |
11+
| 📁 [Base Options](base-options.md) | 9 | Input/output configuration |
1212
| 🔧 [Typing Customization](typing-customization.md) | 27 | Type annotation and import behavior |
1313
| 🏷️ [Field Customization](field-customization.md) | 24 | Field naming and docstring behavior |
1414
| 🏗️ [Model Customization](model-customization.md) | 39 | Model generation behavior |
@@ -161,6 +161,8 @@ This documentation is auto-generated from test cases.
161161

162162
### S {#s}
163163

164+
- [`--schema-version`](base-options.md#schema-version)
165+
- [`--schema-version-mode`](base-options.md#schema-version-mode)
164166
- [`--set-default-enum-member`](field-customization.md#set-default-enum-member)
165167
- [`--shared-module-name`](general-options.md#shared-module-name)
166168
- [`--skip-root-model`](model-customization.md#skip-root-model)

docs/cli-reference/quick-reference.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ datamodel-codegen [OPTIONS]
2222
| [`--input-model`](base-options.md#input-model) | Import a Python type or dict schema from a module. |
2323
| [`--input-model-ref-strategy`](base-options.md#input-model-ref-strategy) | Strategy for referenced types when using --input-model. |
2424
| [`--output`](base-options.md#output) | Specify the destination path for generated Python code. |
25+
| [`--schema-version`](base-options.md#schema-version) | Schema version to use for parsing. |
26+
| [`--schema-version-mode`](base-options.md#schema-version-mode) | Schema version validation mode (strict: warn on OpenAPI extensions). |
2527
| [`--url`](base-options.md#url) | Fetch schema from URL with custom HTTP headers. |
2628

2729
### 🔧 Typing Customization
@@ -299,6 +301,8 @@ All options sorted alphabetically:
299301
- [`--remove-special-field-name-prefix`](field-customization.md#remove-special-field-name-prefix) - Remove the special prefix from field names.
300302
- [`--reuse-model`](model-customization.md#reuse-model) - Reuse identical model definitions instead of generating dupl...
301303
- [`--reuse-scope`](model-customization.md#reuse-scope) - Scope for model reuse detection (root or tree).
304+
- [`--schema-version`](base-options.md#schema-version) - Schema version to use for parsing.
305+
- [`--schema-version-mode`](base-options.md#schema-version-mode) - Schema version validation mode (strict: warn on OpenAPI exte...
302306
- [`--set-default-enum-member`](field-customization.md#set-default-enum-member) - Set the first enum member as the default value for enum fiel...
303307
- [`--shared-module-name`](general-options.md#shared-module-name) - Customize the name of the shared module for deduplicated mod...
304308
- [`--skip-root-model`](model-customization.md#skip-root-model) - Skip generation of root model when schema contains nested de...

docs/supported_formats.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Supported Schema Formats and Versions
2+
3+
This document details the schema formats and versions supported by datamodel-code-generator, including version-specific features and behaviors.
4+
5+
## Supported Versions
6+
7+
### JSON Schema
8+
9+
| Version | $schema URI Pattern | Status |
10+
|---------|---------------------|--------|
11+
| Draft 4 | `draft-04` | Supported |
12+
| Draft 6 | `draft-06` | Supported |
13+
| Draft 7 | `draft-07` | Supported (Default) |
14+
| Draft 2019-09 | `2019-09` | Supported |
15+
| Draft 2020-12 | `2020-12` | Supported |
16+
17+
### OpenAPI
18+
19+
| Version | openapi Field | Status |
20+
|---------|---------------|--------|
21+
| 3.0.x | `3.0.*` | Supported |
22+
| 3.1.x | `3.1.*` | Supported (Default) |
23+
24+
## Version Detection
25+
26+
The parser automatically detects schema versions using the following priority:
27+
28+
1. **Explicit `$schema` field** (JSON Schema) or **`openapi` field** (OpenAPI)
29+
2. **Heuristic detection** based on keywords:
30+
- `$defs` present: Draft 2020-12 (also valid in 2019-09)
31+
- `definitions` present: Draft 7
32+
3. **Fallback**: Draft 7 for JSON Schema, 3.1 for OpenAPI
33+
34+
### Manual Override
35+
36+
Use CLI options to override automatic detection:
37+
38+
```bash
39+
# Specify JSON Schema version
40+
datamodel-codegen --input schema.json --schema-version draft-07
41+
42+
# Specify OpenAPI version
43+
datamodel-codegen --input openapi.yaml --schema-version 3.0
44+
```
45+
46+
## Feature Compatibility by Version
47+
48+
### JSON Schema Features
49+
50+
| Feature | Draft 4 | Draft 6 | Draft 7 | 2019-09 | 2020-12 |
51+
|---------|---------|---------|---------|---------|---------|
52+
| `null` in type array | - | - | - | - | Yes |
53+
| `$defs` (vs `definitions`) | - | - | - | Yes | Yes |
54+
| `prefixItems` (vs items array) | - | - | - | - | Yes |
55+
| Boolean schemas | - | Yes | Yes | Yes | Yes |
56+
| `$id` (vs `id`) | - | Yes | Yes | Yes | Yes |
57+
| Numeric `exclusiveMinimum/Maximum` | - | Yes | Yes | Yes | Yes |
58+
59+
### OpenAPI Features
60+
61+
| Feature | 3.0.x | 3.1.x |
62+
|---------|-------|-------|
63+
| `nullable` keyword | Yes | Deprecated |
64+
| `null` in type array | - | Yes |
65+
| Discriminator | Yes | Yes |
66+
| `$defs` support | - | Yes |
67+
68+
## Data Type Formats
69+
70+
### Common Formats (All Versions)
71+
72+
| Type | Format | Python Type |
73+
|------|--------|-------------|
74+
| `integer` | `int32` | `int` |
75+
| `integer` | `int64` | `int` |
76+
| `number` | `float` | `float` |
77+
| `number` | `double` | `float` |
78+
| `number` | `decimal` | `Decimal` |
79+
| `string` | `date` | `date` |
80+
| `string` | `date-time` | `datetime` |
81+
| `string` | `time` | `time` |
82+
| `string` | `duration` | `timedelta` |
83+
| `string` | `email` | `EmailStr` |
84+
| `string` | `uri` | `AnyUrl` |
85+
| `string` | `uuid` | `UUID` |
86+
| `string` | `uuid1`-`uuid5` | `UUID1`-`UUID5` |
87+
| `string` | `hostname` | `str` |
88+
| `string` | `ipv4` | `IPv4Address` |
89+
| `string` | `ipv6` | `IPv6Address` |
90+
| `string` | `byte` | `bytes` |
91+
| `string` | `path` | `Path` |
92+
93+
### OpenAPI-Only Formats
94+
95+
These formats are only valid in OpenAPI specifications:
96+
97+
| Type | Format | Python Type |
98+
|------|--------|-------------|
99+
| `string` | `binary` | `bytes` |
100+
| `string` | `password` | `SecretStr` |
101+
102+
## Version Modes
103+
104+
### Lenient Mode (Default)
105+
106+
- Accepts all features regardless of declared version
107+
- No warnings for version mismatches
108+
- Recommended for most use cases
109+
110+
### Strict Mode
111+
112+
Enable with `--schema-version-mode strict`:
113+
114+
- Warns when features don't match the declared/detected version
115+
- Useful for schema validation and compliance checking
116+
117+
```bash
118+
# Enable strict mode
119+
datamodel-codegen --input schema.json --schema-version-mode strict
120+
```
121+
122+
**Strict mode warnings include:**
123+
124+
| Feature | JSON Schema Warning | OpenAPI Warning |
125+
|---------|---------------------|-----------------|
126+
| `null` in type array | Draft 4/6/7 (not supported) | 3.0 (use nullable instead) |
127+
| `nullable` keyword | Always (OpenAPI extension) | 3.1 (deprecated) |
128+
| `binary` format | Always (OpenAPI extension) | Never (valid) |
129+
| `password` format | Always (OpenAPI extension) | Never (valid) |
130+
| `prefixItems` | Before Draft 2020-12 | - |
131+
| Items as array | Draft 2020-12 (use prefixItems) | - |
132+
| Boolean schema | Draft 4 (not supported) | - |
133+
| Numeric exclusiveMin/Max | Draft 4 (use boolean) | 3.0 (use boolean) |
134+
| Boolean exclusiveMin/Max | Draft 6+ (use numeric) | 3.1 (use numeric) |
135+
136+
## Limitations
137+
138+
### JSON Schema
139+
140+
- `$dynamicRef`/`$dynamicAnchor` (Draft 2020-12): Not fully supported
141+
- Complex `if`/`then`/`else` patterns: Limited support
142+
- `unevaluatedProperties`/`unevaluatedItems`: Not supported
143+
144+
### OpenAPI
145+
146+
- Callbacks: Not supported
147+
- Links: Not supported
148+
- Security schemes: Parsed but not used for model generation
149+
150+
## Migration Guide
151+
152+
### From OpenAPI 3.0 to 3.1
153+
154+
1. Replace `nullable: true` with `type: ["string", "null"]`
155+
2. Replace `definitions` with `$defs`
156+
3. Update `exclusiveMinimum`/`exclusiveMaximum` from boolean to numeric values
157+
158+
### From JSON Schema Draft 7 to 2020-12
159+
160+
1. Replace `definitions` with `$defs`
161+
2. Replace items array with `prefixItems`
162+
3. Update `id` to `$id`
163+
164+
## See Also
165+
166+
### JSON Schema Specifications
167+
168+
- [JSON Schema Home](https://json-schema.org/)
169+
- [Draft 4](https://json-schema.org/specification-links#draft-4)
170+
- [Draft 6](https://json-schema.org/specification-links#draft-6)
171+
- [Draft 7](https://json-schema.org/specification-links#draft-7)
172+
- [Draft 2019-09](https://json-schema.org/specification-links#2019-09-formerly-known-as-draft-8)
173+
- [Draft 2020-12](https://json-schema.org/specification-links#2020-12)
174+
175+
### OpenAPI Specifications
176+
177+
- [OpenAPI Initiative](https://www.openapis.org/)
178+
- [OpenAPI 3.0.3](https://spec.openapis.org/oas/v3.0.3)
179+
- [OpenAPI 3.1.0](https://spec.openapis.org/oas/v3.1.0)
180+
181+
### datamodel-code-generator
182+
183+
- [CLI Reference](cli-reference/index.md)
184+
- [GitHub Repository](https://github.com/koxudaxi/datamodel-code-generator)

0 commit comments

Comments
 (0)