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

Model property not optional when referencing a nullable subschema

Open grant-zietsman opened this issue 10 months ago • 2 comments

Describe the bug

Given an OpenAPI component schema configured with nullable: true, properties referencing this schema are not generated as optional.

To Reproduce

Example schema (OpenAPI):

openapi: 3.0.3
components:
  schemas:
    Parent:
      type: object
      required:
        - child
      properties:
        child:
          $ref: "#/components/schemas/Child"
    Child:
      nullable: true
      type: object
      required:
        - value
      properties:
        value:
          type: string

Used commandline:

datamodel-code-generator datamodel-codegen \
    --input ... \
    --input-file-type openapi \
    --output-model-type typing.TypedDict \
    --target-python-version 3.12 \
    --strict-nullable \
    --use-annotated \
    --use-field-description \
    --use-schema-description \
    --use-standard-collections \
    --use-union-operator \
    --disable-timestamp

Model output

# generated by datamodel-codegen:
#   filename:  openapi.yaml

from __future__ import annotations

from typing import TypedDict


class Child(TypedDict):
    value: str


class Parent(TypedDict):
    child: Child

Expected behavior It is expected that the child property of the Parent model be optional.

Model output

# generated by datamodel-codegen:
#   filename:  openapi.yaml

from __future__ import annotations

from typing import TypedDict


class Child(TypedDict):
    value: str


class Parent(TypedDict):
    child: Child | None

Version:

  • OS: iOS 15.1.1
  • Python version: 3.12.4
  • datamodel-code-generator version: 0.26.4

grant-zietsman avatar Dec 29 '24 10:12 grant-zietsman

I should have a simple fix that I can submit. But just to make sure, in this example in tests, this field is defined as nullable. https://github.com/koxudaxi/datamodel-code-generator/blob/ef0c97cb34d753aa831fe9f4e71df399d90d746b/tests/data/openapi/nullable.yaml#L17-L19

Wouldn't this mean that this line https://github.com/koxudaxi/datamodel-code-generator/blob/ef0c97cb34d753aa831fe9f4e71df399d90d746b/tests/data/expected/main/openapi/nullable.py#L13 should rather be prev: Optional[str] = None

Currently this test passes, but it should fail as explained in this issue.

taha-yassine avatar Mar 10 '25 05:03 taha-yassine

Thanks for following up on this @taha-yassine.

Yes, that is my understanding.

grant-zietsman avatar Mar 10 '25 10:03 grant-zietsman

Hey guys I too have fallen in to this trap.

I created this small script to performing post patching to get me going while (hopefully) you guys get a proper fix upstream.

https://github.com/cowdao-grants/cow-py/blob/07d9652e552b8b9a63c1af6ee4b75c576512f29f/cowdao_cowpy/post_process.py

8ball030 avatar Jul 14 '25 11:07 8ball030

Hey guys I've also have a very similar problem, but I'm not sure if the root cause is the same. Only difference is that my nullable is under the parent object instead of the referenced child object

        parent_device:
          allOf:
          - $ref: '#/components/schemas/NestedDevice'
          nullable: true
          readOnly: true

Output

parent_device: NestedDevice

Expected

parent_device: NestedDevice | None

For reference, this is the Netbox 4.3 openapi https://demo.netbox.dev/api/schema/swagger-ui/#/dcim/dcim_devices_list

gcoe95 avatar Jul 15 '25 15:07 gcoe95

Yeah, almost certainly the exact same issue. I'd be interested to know if the chatgpt script worked for you

8ball030 avatar Jul 15 '25 18:07 8ball030