Skip to content

Write nil, not :null, in pre-encoded JSON; per-call nil_fields option - #47

Merged
andreashasse merged 10 commits into
mainfrom
andreashasse/pre-encoded-nil
Oct 31, 2026
Merged

andreashasse merged 10 commits into
mainfrom
andreashasse/pre-encoded-nil

Conversation

@andreashasse

Copy link
Copy Markdown
Owner

Draft: waiting for user feedback before merge and release. This is one of four aligned PRs. The Elixir ones depend on the others through git branches, so the whole set can be tried together. Nothing is released yet; the git dependencies go back to Hex versions after feedback. Depends on andreashasse/spectra#204.

  • The 0.16 bug: with config :spectra, :nil_fields, :null, Spectral.encode(..., [:pre_encoded]) returned the atom :null, which Jason and Phoenix encode as the string "null". phoenix_spectral responses and ecto_spectral JSONB storage both go through that path. Pre-encoded JSON now holds nil, in nested maps and lists too. Iodata output was already correct.
  • Per-call option: Spectral.encode/5 and encode!/5 accept nil_fields: :null | :omit and pass it to spectra. With global :omit, :null raises ArgumentError, and with global :null, :omit does too.
  • README: documents the three global values, the per-call option, and how to keep the old schema with config :spectra, :nil_fields, :omit.
  • Dependency: mix.exs temporarily points :spectra at its PR branch.

make ci passes (322 tests), and so does mix docs.

🤖 Generated with Claude Code

andreashasse and others added 5 commits October 31, 2026 01:03
With nil_fields set to null, spectra writes JSON null as the atom :null
in pre-encoded terms. Jason and JSON encode that atom as the string
"null", so callers such as phoenix_spectral sent "null" strings.
Spectral.encode now maps :null to nil in pre-encoded JSON results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spectral.encode/5 and encode!/5 now document and type the
nil_fields: :null | :omit option, which spectra's unreleased
nil-fields-per-call branch reads to choose, for one call, whether nil
fields are written as null or left out. Pre-encoded results map :null
to nil for this option too.

spectra is taken from that branch until 0.17 is released. Its new
default nil_fields setting, :omit_or_null, lets the schema of a
nilable field allow null; config :spectra, :nil_fields, :omit keeps the
old schema. Error context messages from spectra are now binaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cover the list clause of null_to_nil with a [String.t() | nil] value,
and stop claiming spectra sends charlist messages: it uses binaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
andreashasse and others added 5 commits October 31, 2026 01:34
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@andreashasse
andreashasse marked this pull request as ready for review October 31, 2026 08:06
@andreashasse
andreashasse merged commit f18d083 into main Oct 31, 2026
3 checks passed
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.

1 participant