Skip to content

Feature: opt-in per-constant descriptions for enum in JacksonOutputConverter - #2072

Open
sumitvairagar wants to merge 1 commit into
embabel:mainfrom
sumitvairagar:fix/2028-enum-constant-json-property-description
Open

sumitvairagar wants to merge 1 commit into
embabel:mainfrom
sumitvairagar:fix/2028-enum-constant-json-property-description

Conversation

@sumitvairagar

Copy link
Copy Markdown

Closes #2028

What

Adds JacksonOutputConverterOption.ENUM_CONSTANT_DESCRIPTIONS — an opt-in flag that installs a CustomDefinitionProviderV2 to emit per-constant @JsonPropertyDescription annotations as oneOf/const/description instead of a bare enum array.

val converter = JacksonOutputConverter(
    MyResult::class.java,
    objectMapper,
    options = setOf(JacksonOutputConverterOption.ENUM_CONSTANT_DESCRIPTIONS),
)

For an enum like:

enum class Priority {
    @JsonPropertyDescription("Needs same-day response") URGENT,
    @JsonPropertyDescription("Standard turnaround")    NORMAL,
    OTHER
}

the schema becomes:

{ "oneOf": [
    { "const": "URGENT", "description": "Needs same-day response" },
    { "const": "NORMAL", "description": "Standard turnaround" },
    { "const": "OTHER" }
]}

Why opt-in

As discussed in #2028, oneOf is not supported by OpenAI native structured-output strict mode and causes schema fallback to the prompt-based path on that provider. The opt-in flag makes this a conscious choice — consumers on Google GenAI, Anthropic, or the prompt-based path can enable it; the default path stays unchanged and OpenAI strict mode is unaffected.

Enums whose constants carry no @JsonPropertyDescription are unaffected regardless of the option.

Tests

Four new tests in EnumConstantDescriptionTests:

  • without option: bare enum array (unchanged behaviour)
  • with option: annotated enum becomes oneOf/const/description
  • with option: enum inside a List<>\ also becomes oneOf`
  • with option: enum with no annotations stays as bare enum

All 55 tests pass.

When JacksonOutputConverterOption.ENUM_CONSTANT_DESCRIPTIONS is passed,
enum constants annotated with @JsonPropertyDescription are emitted as
oneOf [ { const, description }, ... ] instead of a bare enum array,
so the model receives the prose written for each option.

The option is opt-in because oneOf is not supported by OpenAI native
structured-output strict mode and would cause schema fallback to the
prompt-based path on that provider. Enums with no annotated constants
are unaffected regardless of the option.

Closes embabel#2028
@igordayen igordayen changed the title feat: opt-in per-constant descriptions for enum in JacksonOutputConverter Feature: opt-in per-constant descriptions for enum in JacksonOutputConverter Sep 26, 2026
@igordayen
igordayen self-requested a review September 26, 2026 16:10
@igordayen

Copy link
Copy Markdown
Contributor

@sumitvairagar - thanks for the contribution.
Could you please sign the commit?
Please use uppercase in the PR description in the future (the PR description was generated by a coding agent, I assume)
I will reserve time for a thorough manual review and allocate the milestone accordingly
looping @LiveNathan

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.

JacksonOutputConverter drops enum constants' @JsonPropertyDescription (field descriptions survive; not fixed by registering JacksonModule)

2 participants