Skip to content

fix: preserve omitted and null JSON request bodies - #1488

Open
CodingCossack wants to merge 2 commits into
openapi-generators:mainfrom
CodingCossack:fix/1425-nullable-request-body
Open

CodingCossack wants to merge 2 commits into
openapi-generators:mainfrom
CodingCossack:fix/1425-nullable-request-body

Conversation

@CodingCossack

@CodingCossack CodingCossack commented Sep 15, 2026

Copy link
Copy Markdown

Fixes #1425

Problem

An optional nullable primitive request body, for example {type: number, nullable: true} without required: true, generated an endpoint containing an orphan else:, so the generated client did not compile. A syntax-only repair would still be wrong: HTTPX treats json=None as "no body", so an explicit None and an omitted argument would both send an empty body.

Change

Only openapi_python_client/templates/endpoint_macros.py.jinja changes in production code. The JSON body macro now:

  1. uses the normal property transform (default skip_unset=False), which avoids the broken union branch;
  2. removes the json kwarg when the serialised value is UNSET;
  3. replaces the json kwarg with content=b"null" when the value is None.

Presence and nullability stay independent:

Caller input Request body
Omitted or UNSET empty
None null
Value, including 0, False, "" its JSON

Signature requiredness, nested model serialisation, other body types and the declared Content-Type are unchanged. The 17 golden-record diffs are this boundary logic only.

Tests

New functional tests generate clients from inline OpenAPI 3.0 and 3.1 specs and assert the actual request bytes through httpx.MockTransport, sync and async, for nullable primitives, type lists, anyOf/oneOf, required/optional combinations, date-time, model, array and nested nullable fields, a custom JSON media type, and a query parameter named json_body with strict mypy on the generated package. The file fails on main (generated package does not compile) and passes with this change.

pdm run check passes locally: 480 tests, five snapshots, Ruff and mypy with HTTPX 0.28.1. All 12 new regression tests also pass with installed HTTPX 0.23.1 and 0.27.2. Structured object/array assertions compare decoded JSON, so valid differences in encoder whitespace do not fail the tests; omission, explicit null and primitive values retain exact-byte assertions. An independent review also generated clients from a further set of body shapes (required nullable model, nullable list/date/uuid, Any, single-member unions, form and multipart) and found no regressions.

CodingCossack and others added 2 commits September 15, 2026 18:08
An optional nullable primitive request body rendered an orphan `else:` in
the generated endpoint, so the client did not compile. The JSON body macro
now uses the normal property transform, drops the `json` kwarg when the
serialised value is UNSET, and sends explicit None as raw `content=b"null"`
because HTTPX treats `json=None` as no body. Signature requiredness, nested
serialisation and declared Content-Type are unchanged.

Add generated-client regressions for OpenAPI 3.0 and 3.1 nullable bodies
that assert request bytes through HTTPX for omitted, UNSET, None and
concrete values, and regenerate the affected endpoint golden records.

Fixes openapi-generators#1425

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generates invalid python code for seemingly correct json

1 participant