Repository navigation
[integrations][java] List Jackson enum values in OpenAI, Azure and Anthropic native schemas - #1247
Merged
Merged
Conversation
…ry field Adds PojoJsonSchemaGenerator.generateAllRequired, which derives the same schema as generate except that every field, including an Optional one, is listed as required. It is the required set OpenAI's strict mode expects, and it lets the OpenAI, Azure OpenAI and Anthropic connections move off the SDK's schema builder without changing their required set. Generated-by: GitHub Copilot CLI 1.0.95 (claude-opus-5.5)
…ed generator The OpenAI Chat Completions, Azure OpenAI and Anthropic connections derived their native structured-output schema through the SDK's typed builders. Those schemas list an enum constant by its Java name even when @JsonProperty or @jsonvalue names it differently, so strict mode confines the model to values the response then fails to deserialize from (apache#1246). Derive the schema with PojoJsonSchemaGenerator.generateAllRequired instead, which lists enum constants the way Jackson deserializes them and keeps the strict-mode shape the SDK schemas had: every property required (an Optional field admits null) and no additional properties. The two OpenAI copies of the helper become one in OpenAIChatCompletionsUtils; vLLM inherits the fix through OpenAICompletionsConnection. The schema otherwise matches the SDK's, except that properties now follow declaration order instead of alphabetical order, and Swagger 2 @Schema annotations are no longer read. Generated-by: GitHub Copilot CLI 1.0.95 (claude-opus-5.5)
wenjin272
approved these changes
Oct 14, 2026
wenjin272
left a comment
Contributor
There was a problem hiding this comment.
Thanks for fixing this. LGTM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked issue: #1246
Purpose of change
When an output schema has an enum whose constants carry
@JsonPropertyor a@JsonValuemethod, the native schema sent by the OpenAI Chat Completions, Azure OpenAI and Anthropic connections (and vLLM, which extends the OpenAI one) now lists the values Jackson reads. Before, it listed the Java constant names, the provider held the model to them, and the reply failed to parse.These three connections built the schema through their SDKs' structured-output builders, which ignore Jackson's enum annotations. Ollama, Gemini, Bedrock and watsonx already use the shared
PojoJsonSchemaGenerator, so this moves the three onto it. One enum rule then holds for every Java provider, and it matches Python.Runtime flow
buildRequestdecides whether the schema travels natively, unchanged.OpenAIChatCompletionsUtils.toNativeResponseFormat(OpenAI, Azure, vLLM) orAnthropicChatModelConnection.toNativeOutputConfigcallsPojoJsonSchemaGenerator.generateAllRequired(schemaClass, FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT).json_schemaresponse format namedjson-schema-from-<SimpleName>withstrict: true, or Anthropic'soutput_config.format.Key decisions
generateAllRequirednext togenerate. OpenAI strict mode rejects a schema whoserequiredomits a property, whilegenerateleavesOptionalfields out. The new method differs only in the required set; anOptionalfield stays nullable.JacksonModule().OpenAIChatCompletionsUtilsreplaces the identical copies in the two OpenAI-SDK connections.Behavioral Semantics
Interaction decisions
@JsonPropertyon every constant@JsonValuemethod returning aString@JsonPropertyon only some constants@JsonValuemethod returning a number"type": "string"(was: names), as on the other four providersBehavioral contracts
@JsonProperty, or through aString@JsonValuemethod, is listed by the values Jackson deserializes.requiredset, at every level; anOptionalfield is required and admitsnull.Failure behavior
@JsonValueenum's schema may now be rejected by the provider where it previously failed at parse time.IllegalStateExceptionfor a missing response format or output config is gone; the generator always returns a schema.Tests
derivedSchemaFollowsJacksonEnumValuesinOpenAICompletionsConnectionTest,AzureOpenAIChatModelConnectionTest,AnthropicChatModelConnectionTestderivedSchemaRequiresEveryFieldAndForbidsExtras(OpenAI Completions, Anthropic);PojoJsonSchemaGeneratorTest.allRequiredRequiresOptionalFieldsAsNullable,allRequiredChangesOnlyTheRequiredSettestNativeAppliedForPojoCapableModel,testNativeAppliedForCapableDeploymentModeltestPolymorphicMemberSchemaIsSent(all three)testNativeNotApplied*,testNativeSchemaNotAppliedWithoutSchema,testNonClassSchemaKeepsFallbackThe three enum tests fail without the connection change, at the enum round-trip, with Jackson rejecting
"IN_PROGRESS".Commands, JDK 17:
mvn -B --no-transfer-progress -pl integrations/chat-models/common,integrations/chat-models/openai,integrations/chat-models/anthropic clean test: passed (8, 148, 103 tests, 0 failures)../tools/check-license.sh: passed.Not verified:
@JsonValueenum schema.Schema snapshot before and after, and implementation invariants
Fourteen fixtures were rendered through both the old SDK path and the new one: enums (all
@JsonProperty,String@JsonValue, partial@JsonProperty, numeric@JsonValue, plain),Optionalwith a nested object and@JsonPropertyDescription, collections, primitives,@JsonPropertyrename with@JsonIgnore, a getter bean, a@JsonTypeInfo/@JsonSubTypesmember, a recursive type, an inherited type, and a plain POJO.The only differences:
@JsonProperty,String@JsonValueand numeric@JsonValuefixtures.Identical before and after:
$schema, everyrequiredset,additionalProperties: falseat every level,Optionalas["string", "null"], the polymorphicanyOfwithconstdiscriminators, descriptions, and the OpenAI format name,strictandtype. Before and after, Azure and OpenAI Completions send the same response format, and Anthropic sends the same schema as OpenAI.Implementation invariants:
generateAllRequiredandgenerateshare one body and differ only in the required-field check;allRequiredChangesOnlyTheRequiredSetcompares the two outputs withrequiredremoved.ObjectNode's fields in order, so the SDK serializes properties in the generator's order.openaiandanthropicnow depend onflink-agents-integrations-chat-models-commonandjsonschema-generator(BOM-managed), whichdistalready bundles for the other providers.API
No public API changes for agent code.
PojoJsonSchemaGeneratorgainsgenerateAllRequired(Class<?>, Option...);generateis unchanged.For existing callers of these three connections:
@Schemaannotations on the schema class are no longer read. Jackson annotations, including@JsonPropertyDescription, still are.Documentation
doc-neededdoc-not-neededdoc-includedWas this patch authored or co-authored using generative AI tooling?
Generated-by: GitHub Copilot CLI 1.0.95 (claude-opus-5.5)