Skip to content

custom optional support#2390

Merged
stephenberry merged 4 commits intomainfrom
custom-optional
Mar 22, 2026
Merged

custom optional support#2390
stephenberry merged 4 commits intomainfrom
custom-optional

Conversation

@stephenberry
Copy link
Copy Markdown
Owner

@stephenberry stephenberry commented Mar 20, 2026

Fix glz::custom getter returning nullopt not being omitted

Fixes #2386

When a glz::object field uses glz::custom<setter, getter> and the getter returns a nullable type (e.g. std::optional<T>), the field was always serialized — even when the getter returned std::nullopt. With skip_null_members = true (the default), the expected behavior is to omit the field entirely, consistent with how plain std::optional members and nullable lambdas are handled.

The root cause is that the skip-null check in the object write path operates on field_t, which for custom fields is custom_t<...> — a wrapper that does not satisfy null_t. The nullable return type of the getter is never inspected.

Changes

include/glaze/core/reflect.hpp

  • Added custom_getter_returns_nullable<V>(): compile-time trait that inspects the getter's return type across all supported forms (member function pointers, member object pointers, std::function members, concrete lambdas, generic lambdas, context-taking invocables).
  • Added custom_getter_is_null(): runtime helper that invokes the getter and checks whether the result is null. Reused by all three format writers.
  • Updated maybe_skipped to include custom_t fields whose getters return nullable types, so the dynamic-skip path is entered when needed.

include/glaze/json/write.hpp

  • Added an else if constexpr branch for custom_t with nullable getter in the object field write loop. Invokes the getter via custom_getter_is_null() and skips the field if null.

include/glaze/cbor/write.hpp

  • Same fix in both the count pass and write pass of the CBOR object serializer.

include/glaze/beve/write.hpp

  • Same fix in both the count pass and write pass of the BEVE object serializer.

tests/json_test/nullable_lambda_test.cpp

  • Added 3 test cases using glz::custom<setter, getter> with an std::optional<std::string> getter:
    • Getter returns std::nullopt → field omitted
    • Getter returns a value → field written
    • skip_null_members = false → field written as null

@stephenberry stephenberry merged commit 7b2ffd8 into main Mar 22, 2026
47 of 48 checks passed
@stephenberry stephenberry deleted the custom-optional branch March 22, 2026 19:23
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.

glz::custom getter returning std::nullopt results in JSON field with null instead of being omitted

1 participant