Skip to content

feat(codecs): add empty_or_null codec for nullable typed codes across Rust and Go - #382

Merged
benbenbang merged 3 commits into
mainfrom
feat/368-f0-empty-codec
Sep 30, 2026
Merged

benbenbang merged 3 commits into
mainfrom
feat/368-f0-empty-codec

Conversation

@benbenbang

Copy link
Copy Markdown
Member

Providers sometimes send nullable typed codes as an empty string or JSON null on a key that is otherwise required. To handle these consistently and safely, this change introduces a dedicated codec that maps both spellings to an absent value while keeping decode errors from leaking the offending input, as specified by ADR 0033.

What changed:

  • Added the empty_or_null field codec in libfmp, decoding "" and null to None, parsing other values via FromStr, keeping the key required, and re-encoding None as null.
  • Extended the Go model generator with an EmptyOrNullString variant that maps an optional string-backed scalar to a nil-able *string backed by a jsontext.Value shadow, rejecting unsupported shapes with a clear error.
  • Added tests on both sides covering empty/null-to-absent mapping, round-trip serialization, required-key and missing-field handling, rendered tags and unmarshal bodies, and that decode errors never echo the value.
  • Documented the behaviour by adding ADR 0033, updating ADRs 0001 and 0030 for the wire evidence and new Go codec, and linking ADR 0033 in the design index.

This adds a new field codec that decodes a required wire key holding a
typed code whose absent value the provider sends as `""` or JSON null,
per ADR 0033 (#368). Both spellings decode to `None`, while any other
value is parsed with the type's `FromStr`, so whitespace-only or
control-bearing input remains a decode error that never echoes the value.
The key stays required, matching `required_option`, and `None` re-encodes
as null through serde's default serialization.

**New codec:**
* Added the `empty_or_null` module in `crates/libfmp/src/codecs.rs`,
  applied via `deserialize_with = "crate::codecs::empty_or_null::deserialize"`
  (the exact path gen_go matches).
* Added a test covering empty/null-to-`None` mapping, round-trip
  serialization, missing-field errors, and that decode errors never
  contain the offending value.

**Documentation:**
* Added ADR 0033 describing nullable response members.
* Extended ADR 0001 to cover observed wire evidence where a typed code or
  date seen as `""` or null decodes to `None`.
* Updated ADR 0030 to document the fifth Go field codec introduced by
  ADR 0033.
This pull request adds support for the `empty_or_null` typed-code codec in
the Go model generator, so Rust fields using
`crate::codecs::empty_or_null::deserialize` on an `Option` of a
string-backed type map to a nil-able Go pointer.

**Codec support:**
* Added the `EmptyOrNullString` variant and its `EMPTY_OR_NULL_CODEC`
  path, mapping an `Option` of a string-backed scalar to a `*string`
  public type backed by a `jsontext.Value` shadow, and rejecting any
  other shape with an explanatory error.
* Treated the key as required and decoded both `""` and null to nil
  through the raw shadow, per ADR 0033.

**Testing:**
* Added a test that decodes empty and null values to nil through the raw
  shadow, checks the rendered public and shadow tags, the required-key
  handling, and the generated unmarshal body, and asserts that
  non-string and bare shapes fail with an `empty_or_null` error.
Link ADR 0033 in the design index, covering nullable response members
and how `""` or null on typed codes and dates decode to `None` / `nil`
based on observed wire evidence.
@benbenbang
benbenbang enabled auto-merge (rebase) September 30, 2026 12:14
@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Sep 30, 2026
@benbenbang
benbenbang merged commit 76543d1 into main Sep 30, 2026
9 checks passed
@benbenbang
benbenbang deleted the feat/368-f0-empty-codec branch September 30, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant