datamodel-code-generator
datamodel-code-generator copied to clipboard
Add a --default-factory flag to set nested types
Is your feature request related to a problem? Please describe.
I'm using pydantic to parse raw data in a dataflow pipeline. This comes with a lot of nested data models where the inner field sometimes will be empty. These will cause error when calling a nested model that does not exist. The current solution is just to use: x = A.B.c if A.B else None similar to the x = A.get("B",{}).get("c") when using dictionaries.
Describe the solution you'd like
I want a flag --default-factory that sets the default value to an empty version of the datamodel:
Hence: Currently a normal generation gives:
class B_model(BaseModel):
c = Optional[List]=None
class A_model(BaseModel):
B = Optional[B_model] = None
This works with input json {"A":{"B": {"c":[]} }} but I could also get {"A":None}.
class B_model(BaseModel):
c = Optional[List]= None
class A_model(BaseModel):
B = Optional[B_model] = Field(default_factory=B_model)
By then complementing this solution with a model_validator:
@model_validator(mode="before")
def default_children(cls, values):
for key, value in values.items():
if value is None and (default_factory := getattr(cls.model_fields[key], "default_factory")):
values[key] = default_factory()
return values
I'm able to safely call anything which will just return a None if the field does not exist.
Describe alternatives you've considered
The current solution is just to use: x = A.B.c if A.B else None similar to the x = A.get("B",{}).get("c") when using dictionaries. One could also overwrite the pydantic class methods to do something similar or use Field validators.
I need default factories for generating "@dataclass" classes like this:
Current output:
@dataclass
class CustomOriginConfig:
OriginProtocolPolicy: str
HTTPPort: Optional[int] = 80
HTTPSPort: Optional[int] = 443
OriginKeepaliveTimeout: Optional[int] = 5
OriginReadTimeout: Optional[int] = 30
OriginSSLProtocols: Optional[List[str]] = ['TLSv1', 'SSLv3']
but this doesn't pass typechecking (running uvicorn)
What is required:
@dataclass
class CustomOriginConfig:
OriginProtocolPolicy: str
HTTPPort: Optional[int] = 80
HTTPSPort: Optional[int] = 443
OriginKeepaliveTimeout: Optional[int] = 5
OriginReadTimeout: Optional[int] = 30
OriginSSLProtocols: Optional[List[str]] = field(default_factory=lambda: ['TLSv1', 'SSLv3'])