Skip to content

[Kotlin Spring] fix: Omit example field if not set#24228

Open
wegendt-bosch wants to merge 1 commit into
OpenAPITools:masterfrom
wegendt-bosch:fix/24227-omit-example
Open

[Kotlin Spring] fix: Omit example field if not set#24228
wegendt-bosch wants to merge 1 commit into
OpenAPITools:masterfrom
wegendt-bosch:fix/24227-omit-example

Conversation

@wegendt-bosch

@wegendt-bosch wegendt-bosch commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #24227.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Stop emitting empty example attributes in Kotlin-generated model annotations. Only include example when the schema provides one; removes example = "null" and example = "" from outputs. Fixes #24227.

  • Bug Fixes
    • Updated AbstractKotlinCodegen#toExampleValue to return null unless schema.example is set, preventing default/empty examples from being emitted.
    • Kept kotlin-spring templates dataClassOptVar.mustache and dataClassReqVar.mustache gated so example is included only when provided.

Written for commit 67e597c. Summary will update on new commits.

Review in cubic

@wegendt-bosch

Copy link
Copy Markdown
Contributor Author

cubic is sorta right: it avoids @Schema(example="null")

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/kotlin-spring/dataClassReqVar.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/kotlin-spring/dataClassReqVar.mustache:2">
P2: This line introduces `{{#example?}}`, an uncommon Mustache section syntax with no precedent anywhere else in the project's templates. In standard Mustache, a section pushes its value onto the context stack so `{{{.}}}` resolves correctly; if `example?` is instead a boolean flag or unsupported by the engine, the inner `{{{.}}}` would render the wrong value (e.g., `true` or the parent object) rather than the actual example string. Applying the change only to the swagger2 annotation while leaving the nearly identical swagger1 annotation unchanged adds further uncertainty. Unless the template engine explicitly supports `?` as a value-preserving section guard, this risks silently breaking generated `@Schema` annotations. Consider using the established `{{#example}}` pattern unless there is engine-specific documentation confirming `example?` behaves identically for context resolution.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/kotlin-spring/dataClassOptVar.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/kotlin-spring/dataClassOptVar.mustache:2">
P1: The switch from `{{#example}}` to `{{#example?}}` combined with the unchanged inner `{{{.}}}` is likely to break Swagger v3 `@Schema(example = ...)` output. The original `{{#example}}` pushed the example string onto the Mustache context stack so `{{{.}}}` rendered it correctly. Using `{{#example?}}` either skips the section entirely (if `example?` is unrecognized) or changes the context to a boolean/parent object, causing `{{{.}}}` to emit the wrong value. Please verify the JMustache template engine behavior for `?` modifiers or revert the change for the `swagger2AnnotationLibrary` branch.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@@ -1,5 +1,5 @@
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swagger2AnnotationLibrary}}
@Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
@Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: The switch from {{#example}} to {{#example?}} combined with the unchanged inner {{{.}}} is likely to break Swagger v3 @Schema(example = ...) output. The original {{#example}} pushed the example string onto the Mustache context stack so {{{.}}} rendered it correctly. Using {{#example?}} either skips the section entirely (if example? is unrecognized) or changes the context to a boolean/parent object, causing {{{.}}} to emit the wrong value. Please verify the JMustache template engine behavior for ? modifiers or revert the change for the swagger2AnnotationLibrary branch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/kotlin-spring/dataClassOptVar.mustache, line 2:

<comment>The switch from `{{#example}}` to `{{#example?}}` combined with the unchanged inner `{{{.}}}` is likely to break Swagger v3 `@Schema(example = ...)` output. The original `{{#example}}` pushed the example string onto the Mustache context stack so `{{{.}}}` rendered it correctly. Using `{{#example?}}` either skips the section entirely (if `example?` is unrecognized) or changes the context to a boolean/parent object, causing `{{{.}}}` to emit the wrong value. Please verify the JMustache template engine behavior for `?` modifiers or revert the change for the `swagger2AnnotationLibrary` branch.</comment>

<file context>
@@ -1,5 +1,5 @@
 {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swagger2AnnotationLibrary}}
-    @Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
+    @Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
     @ApiModelProperty({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swagger1AnnotationLibrary}}{{#deprecated}}
     @Deprecated(message = ""){{/deprecated}}{{#vendorExtensions.x-field-extra-annotation}}
</file context>
Suggested change
@Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
@Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

what? {{.}} is inside the example? block, so it's not called at all

@@ -1,5 +1,5 @@
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swagger2AnnotationLibrary}}
@Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
@Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This line introduces {{#example?}}, an uncommon Mustache section syntax with no precedent anywhere else in the project's templates. In standard Mustache, a section pushes its value onto the context stack so {{{.}}} resolves correctly; if example? is instead a boolean flag or unsupported by the engine, the inner {{{.}}} would render the wrong value (e.g., true or the parent object) rather than the actual example string. Applying the change only to the swagger2 annotation while leaving the nearly identical swagger1 annotation unchanged adds further uncertainty. Unless the template engine explicitly supports ? as a value-preserving section guard, this risks silently breaking generated @Schema annotations. Consider using the established {{#example}} pattern unless there is engine-specific documentation confirming example? behaves identically for context resolution.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/kotlin-spring/dataClassReqVar.mustache, line 2:

<comment>This line introduces `{{#example?}}`, an uncommon Mustache section syntax with no precedent anywhere else in the project's templates. In standard Mustache, a section pushes its value onto the context stack so `{{{.}}}` resolves correctly; if `example?` is instead a boolean flag or unsupported by the engine, the inner `{{{.}}}` would render the wrong value (e.g., `true` or the parent object) rather than the actual example string. Applying the change only to the swagger2 annotation while leaving the nearly identical swagger1 annotation unchanged adds further uncertainty. Unless the template engine explicitly supports `?` as a value-preserving section guard, this risks silently breaking generated `@Schema` annotations. Consider using the established `{{#example}}` pattern unless there is engine-specific documentation confirming `example?` behaves identically for context resolution.</comment>

<file context>
@@ -1,5 +1,5 @@
 {{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swagger2AnnotationLibrary}}
-    @Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
+    @Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
     @ApiModelProperty({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swagger1AnnotationLibrary}}{{#vendorExtensions.x-field-extra-annotation}}
     {{{.}}}{{/vendorExtensions.x-field-extra-annotation}}
</file context>
Suggested change
@Schema({{#example?}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example?}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
@Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeInNormalString}}{{{.}}}{{/lambdaEscapeInNormalString}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@wegendt-bosch

Copy link
Copy Markdown
Contributor Author

Hm, actually this disables all emits of example = ... I'll try overriding the function toExampleValue

@wegendt-bosch wegendt-bosch force-pushed the fix/24227-omit-example branch from 4b6b056 to 67e597c Compare July 7, 2026 14:04
*/
data class Pet(

@Schema(example = "doggie", required = true, description = "")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

works now: example is emitted if set

@wegendt-bosch wegendt-bosch changed the title fix: Omit example field if not set [Kotlin Spring] fix: Omit example field if not set Jul 7, 2026
@wegendt-bosch

Copy link
Copy Markdown
Contributor Author

@karismann (2019/03) @Zomzog (2019/04) @andrewemery (2019/10) @4brunu (2019/11) @yutaka0m (2020/03) @stefankoppier (2022/06) @e5l (2024/10) please review :)

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.

[BUG] [Kotlin Spring] Example field is filled when not specified

1 participant