Skip to content

Support three-state optional fields (Optional<T>) for PATCH serialization #1

@OmarAlJarrah

Description

@OmarAlJarrah

Problem

PATCH and JSON Merge Patch operations need to distinguish three states for each field:

  • absent — omit the field; leave the server value unchanged
  • explicit null — send null; clear the server value
  • present — send a concrete value

Plain nullable types (T?) collapse absent and null into a single representation, so models cannot express partial updates faithfully. The initial serialization layer intentionally ships without a dedicated type for this; consumers must hand-roll converters or fall back to JsonNode.

Proposed direction

Introduce a three-state Optional<T> value type (absent / null / present) with:

  • a System.Text.Json converter, and
  • source-generation support that omits absent members on write.

This is the .NET counterpart to the Tristate<T> container the Java and Python SDKs already provide.

Requirements & considerations

  • Trim-safe and NativeAOT-compatible. The converter and the omit-on-absent behavior must work with source-generated JsonSerializerContexts — no runtime reflection.
  • Omission mechanism. Skipping an absent member cannot be expressed through DefaultIgnoreCondition for a struct; it needs a JsonTypeInfo / ShouldSerialize modifier integrated with the source generator.
  • Additive. This can land after the initial serialization work without changing existing public APIs.
  • Ergonomics. Implicit conversion from T, factory helpers (Optional.Of(value), Optional<T>.Absent), and clean pattern matching.

Out of scope (for now)

  • Full RFC 7386 (JSON Merge Patch) document handling, unless we choose to layer it on top of Optional<T>.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions