datamodel-code-generator icon indicating copy to clipboard operation
datamodel-code-generator copied to clipboard

Nullability info excluded from templates for optional, no-default OpenAPI fields

Open Melinysh opened this issue 2 months ago • 0 comments

Describe the bug

When using custom templates, the field.nullable value can be None, even though one is set from the provided OpenAPI spec. We only seem to pass it along with --strict-nullable and for required fields, or fields with a default, otherwise we pass None.

I am trying to do some more custom code generation based off the value of field.nullable, but I am unable to as the value from the spec is not reliably passed along.

To Reproduce

Example schema:

"Money": {
  "properties": {
    "amount": {
      "nullable": false,
      "type": "number"
    },
    "currency": {
      "nullable": false,
      "type": "string"
    }
  },
  "required": [
     "amount"
   ],
   "type": "object"
}

Used commandline:

$ datamodel-codegen --input-file-type openapi --input-file your-input.json --output-model-type pydantic_v2.BaseModel --openapi-scopes "schemas" --strict-nullable --custom-teplate-dir /my/custom/templates/dir 

Expected behavior

If a field is nullable in the openAPI spec (either implicitly or explicitly), then that same nullable value can be accessed in custom templates.

Version:

  • OS: MacOS
  • Python version: 3.10
  • datamodel-code-generator version: 0.25.4

Additional context

The existing logic is related to the changes for https://github.com/koxudaxi/datamodel-code-generator/issues/327. Specifically, the optional, non-nullable case. I would like to generate pydantic models that will raise validation errors if a user tries to initialize an optional, non-nullable field with an explicit None. For example, using the generated model for the above openAPI spec:

Money(amount=1.0, currency=None) # should raise validation error in my opinion, but current logic doesn't
Money(amount=1.0) # ok because currency is optional
Money(amount=1.0, currency='CAD') # ok since currency is not null

My plan is to generate model validator methods on these pydantic models to see if a None value is passed to an optional, non-nullable field vs being left out.

I believe the existing logic for how the tool generates optional, non-nullable fields from OpenAPI specs was influenced by this comment. It is tricky to try and represent nullability & optionality when we just have None available to us in Python. I would have preferred the case where passing None was like passing null and not allowed as per the spec, rather than using an explicit None in this case to represent optional.

As a workaround, because I have control over the generation of the OpenAPI spec I'm using as input, I have added an extra x-optional-non-nullable: true field to the properties I care about. This can be passed properly through to the templating with --field-extra-keys, but this should instead be fixed in this repo.

Melinysh avatar Apr 08 '24 20:04 Melinysh