#Literal null as the default value for an OpenAPI schema property

1 messages · Page 1 of 1 (latest)

dawn hornet
#

Hi, is there a recommended way to have a literal null be used as the default value for a property in the generated OpenAPI schema?

In the following example, I'd like the title property to have a default value of null in the generated OpenAPI schema.

from litestar import Litestar, post
from msgspec import Struct

class TodoItem(Struct):
    title: str | None = None

@post("/")
async def foo(data: TodoItem) -> None:
    pass

app = Litestar(route_handlers=[foo])

Looking at the generated openapi.json, the TodoItem schema does not have a default value for the title property:

  "TodoItem": {
    "properties": {
      "title": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ]
      }
    },
    "type": "object",
    "required": [],
    "title": "TodoItem"
  }

My current workaround is to create a class and encoder so that it will be serialized the same as None, and then set the property to an instance of the class through app.openapi_schema:

from litestar import Litestar, post
from msgspec import Struct

class TodoItem(Struct):
    title: str | None = None

@post("/")
async def foo(data: TodoItem) -> None:
    pass

class JSONNull():
    pass

def jsonnull_enc_hook(obj):
    if isinstance(obj, JSONNull):
        return None
    raise TypeError(f"Cannot encode objects of type {type(obj)}")

app = Litestar(route_handlers=[foo], type_encoders={JSONNull: jsonnull_enc_hook})
app.openapi_schema.components.schemas["TodoItem"].properties["title"].default = JSONNull()

With the workaround, the JSON looks like

  "TodoItem": {
    "properties": {
      "title": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ],
        "default": null
      }
    },
    "type": "object",
    "required": [],
    "title": "TodoItem"
  }
brisk tangleBOT
#
Notes for Literal null as the default value for an OpenAPI schema property
At your assistance

@dawn hornet

No Response?

If no response in a reasonable time, ping @Member.

Closing

To close, type !solve or byte solve.

MCVE

Please include an MCVE so that we can reproduce your issue locally.

dawn hornet
#

The idea behind the workaround is how the JSON is generated in litestar.openapi.controller

https://github.com/litestar-org/litestar/blob/844c90ab25d9de9703fd92c1cdaccc3d65e184f5/litestar/openapi/controller.py#L606

schema = self.get_schema_from_request(request).to_schema()
json_encoded_schema = encode_json(schema, request.route_handler.default_serializer)

to_schema() will not include a key-value pair in the returned dictionary if the value is None https://github.com/litestar-org/litestar/blob/844c90ab25d9de9703fd92c1cdaccc3d65e184f5/litestar/openapi/spec/base.py#L64.

In the first example, the title Schema has default=None which explains its absence. By setting default to an instance of JSONNull, the value for default is not None, so it's included in the returned dictionary from to_schema().
Then when encode_json() encodes the dictionary into JSON, the type encoder we added will encode that value as null.

The workaround feels really cruddy. Are there better ways to use a literal null as the default value? Preferably something that I could do when defining the Struct?

weary perchBOT
#

litestar/openapi/controller.py line 606

schema = self.get_schema_from_request(request).to_schema()

litestar/openapi/spec/base.py line 64

if value is not None: