Summary
The Python renderer's default nice-property-names behavior splits valid identifiers at digit/letter boundaries. For example, the JSON property source_m3u8 becomes the Python field source_m3_u8.
This is surprising for protocol/API fields and causes a practical problem with the existing --pydantic-base-model option: FastAPI/Pydantic validates request bodies against the generated Python field name, but the JSON payload still contains source_m3u8.
Reproduction
Input schema:
{
"type": "object",
"properties": {
"source_m3u8": { "type": "string" }
},
"required": ["source_m3u8"]
}
Generate Python:
quicktype \
--src schema.json \
--src-lang schema \
--lang py \
--python-version 3.7 \
--pydantic-base-model \
--top-level Request
The generated model contains:
class Request(BaseModel):
source_m3_u8: str
Parsing the real API payload fails:
Request.model_validate({"source_m3u8": "https://example.test/live.m3u8"})
# ValidationError: source_m3_u8 - Field required
The generated from_dict helper does reference obj.get("source_m3u8"), but FastAPI/Pydantic does not call that helper when validating a request model.
Using --no-nice-property-names is not an adequate workaround because it produces sourcem3u8, which still does not preserve the original property name.
Proposed behavior
Add an opt-in Python renderer option, for example --keep-property-names:
- default remains
false, preserving current output;
- when enabled, keep the original name if it is a valid Python identifier;
- continue using the existing naming/legalization behavior for invalid identifiers and Python keywords.
This keeps the change backwards compatible while allowing generated Pydantic models to match API JSON keys directly.
Summary
The Python renderer's default
nice-property-namesbehavior splits valid identifiers at digit/letter boundaries. For example, the JSON propertysource_m3u8becomes the Python fieldsource_m3_u8.This is surprising for protocol/API fields and causes a practical problem with the existing
--pydantic-base-modeloption: FastAPI/Pydantic validates request bodies against the generated Python field name, but the JSON payload still containssource_m3u8.Reproduction
Input schema:
{ "type": "object", "properties": { "source_m3u8": { "type": "string" } }, "required": ["source_m3u8"] }Generate Python:
The generated model contains:
Parsing the real API payload fails:
The generated
from_dicthelper does referenceobj.get("source_m3u8"), but FastAPI/Pydantic does not call that helper when validating a request model.Using
--no-nice-property-namesis not an adequate workaround because it producessourcem3u8, which still does not preserve the original property name.Proposed behavior
Add an opt-in Python renderer option, for example
--keep-property-names:false, preserving current output;This keeps the change backwards compatible while allowing generated Pydantic models to match API JSON keys directly.