Skip to content

[BUG][DART] PATCH tri-state optional handling#23696

Open
radelcom wants to merge 4 commits intoOpenAPITools:masterfrom
radelcom:radelcom-fix/dart-patch-tri-state
Open

[BUG][DART] PATCH tri-state optional handling#23696
radelcom wants to merge 4 commits intoOpenAPITools:masterfrom
radelcom:radelcom-fix/dart-patch-tri-state

Conversation

@radelcom
Copy link
Copy Markdown

@radelcom radelcom commented May 5, 2026

Summary

Adds minimal PATCH tri-state handling for dart-dio with built_value serialization.

This fixes the PATCH case where the generator needs to preserve three distinct states for nullable fields:

  • absent
  • present with null
  • present with a value

The PR is intentionally scoped to the serialization path only to keep review risk low.

Changes

  • mark models with wrapped optional PATCH properties using x-has-optional-properties
  • export optional.dart when useOptional=true
  • import optional.dart in generated built_value models when needed
  • initialize wrapped fields with Optional.absent()
  • serialize wrapped fields only when object.field.isPresent
  • emit null when the present wrapped value is null
  • use unwrapped datatype metadata for serializer typing

Validation

Validated locally with:

./mvnw clean package -DskipTests

Build result: success.

Also validated by generating a Dart Dio sample from the built CLI jar. Generation completed successfully.

./mvnw clean package with tests enabled hit unrelated existing Kotlin Spring test failures on the local Java 25 environment, so this PR was validated through successful package build and Dart generation behavior.

How to validate

  1. Build the project:
./mvnw clean package -DskipTests
  1. Generate a Dart Dio client.
  2. Confirm wrapped PATCH fields:
  • default to Optional.absent()
  • are omitted when absent
  • serialize as key: null for Optional.present(null)
  • serialize as key: value for Optional.present(value)

/cc @wing328 @jaumard


Summary by cubic

Fixes PATCH tri-state handling in dart-dio with built_value, covering both serialization and deserialization so optional fields support absent, present-null, and present-value without mis-serialization.

  • Bug Fixes
    • Wrap optional PATCH fields in Optional and default to Optional.absent(); keep the outer Optional non-null (Optional<T?>, not Optional<T?>?).
    • Serialization: emit keys only when isPresent; write null for present-with-null.
    • Deserialization: set Optional.present(value) (including null), keep Optional.absent() when the key is missing; use unwrapped FullType metadata via x-unwrapped-datatype/x-unwrapped-datatype-nullable.
    • Wire-up: export optional.dart when useOptional=true and import it only for models with x-has-optional-properties; avoid whitespace-only template churn.

Written for commit 70b3b61. Summary will update on new commits.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

@wing328
Copy link
Copy Markdown
Member

wing328 commented May 5, 2026

cc @jaumard (2018/09) @josh-burton (2019/12) @amondnet (2019/12) @sbu-WBT (2020/12) @kuhnroyal (2020/12) @agilob (2020/12) @ahmednfwela (2021/08)

radelcom added 2 commits May 6, 2026 08:07
The outer Optional should never be null—only the inner value can be null.
Field type should be Optional<T?>, not Optional<T?>?

This fixes compilation errors when serializer tries to access .isPresent
on a potentially null Optional.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants