Skip to content

Extract spectral_ecto: an Ecto.ParameterizedType for jsonb columns #41

Description

@andreashasse

Follow-up from #40.

Spectral already works with jsonb columns through :pre_encoded and :pre_decoded, which is now documented in the "Spectral and Ecto" README section. What is missing is the packaging, so that a schema can declare a column directly:

field :settings, SpectralEcto.JSONB, module: MyApp.Settings, type: :t

Why a separate repository

It was deliberately left out of this repo:

  • It needs a real Ecto dependency. As an optional dependency here it would need conditional compilation, and this library would take on Ecto version compatibility.
  • Adding ecto even as a test-only dependency pulls in decimal, which currently carries an unfixed MEDIUM advisory (CVE-2026-32686). Every contributor would see a vulnerability warning on mix deps.get with no upgrade available.
  • The interesting tests need a real Postgres instance writing and reading actual jsonb, which this repo's CI does not provision.

A separate repo can depend on Ecto normally, run real database tests, and version against Ecto releases independently.

Scope

An Ecto.ParameterizedType parameterized by module and type name, implementing init/1, type/1, cast/2, load/3, dump/3, equal?/3 and embed_as/2. Two behaviours the tests should pin down, both noted in the README:

  • nil clauses are required. Ecto.Type dispatches to parameterized types before its own nil shortcut (lib/ecto/type.ex, the parameterized clause precedes the nil clause for cast, load and dump alike). A NULL column therefore arrives as nil in all three. Plain Ecto.Type modules never see nil, so this is easy to get wrong when porting one.
  • load/3 and dump/3 can only return :error, losing Spectral's error list. cast/2 can return {:error, message: ...} so changeset validation keeps the detail. Decide deliberately whether load/3 raises instead, since bad data already in the column is a bug rather than user input.

Worth testing against a real database: round trips for both directions, NULL handling, a column declared NOT NULL, and whether a type whose top level is a list maps onto Ecto's :map cleanly.

Once it exists, update the README section to point at it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions