Skip to content

Fix inconsistency between openapi contract and the generated code for URL parameters (Kotlin)#23373

Open
kdefives wants to merge 2 commits intoOpenAPITools:masterfrom
kdefives:patch-3
Open

Fix inconsistency between openapi contract and the generated code for URL parameters (Kotlin)#23373
kdefives wants to merge 2 commits intoOpenAPITools:masterfrom
kdefives:patch-3

Conversation

@kdefives
Copy link
Copy Markdown

@kdefives kdefives commented Mar 27, 2026

Please find below the problem explained and why I suggest this solution:

  • On API contract (yaml file), we can define the endpoint like that:
paths:
  /v1/new_endpoint:
    get:
      operationId: getList
      summary: Get list
      parameters:
        - name: my_parameter
          in: query
          description: My parameter description
          required: true
          schema:
            type: string
            example: "something"
  • We can see above that i explicitly define my parameter using "snake_case" format. Thanks to my API contract, by reading the contract my user will expect to call my endpoint using "snake_case" format for this parameter.

  • Unfortunatly, currently, when openapi generator will generate the code for the Paths.kt file, it will replace the name of the parameter with camelCase. Which is ok in term of Kotlin naming convention for variable naming (cf. example below):

object Paths {
    /**
     * Get list
     * Returns list

     * @param myParameter (ex. something) 
     */
    @Resource("/v1/new_endpoint") class getList(val myParameter: kotlin.String)
}
  • As we can see above, the problem is the parameter my_parameter as been replaced by myParameter. Due to that, my application will expect to be called be parameter [URI]?myParameter=something instead of [URI]?my_parameter=something as indicated within the API contract (yaml file).

  • The solution in Kotlin is to prefix using @SerialName annotation, like that:

object Paths {
    /**
     * Get list
     * Returns list

     * @param myParameter (ex. something) 
     */
    @Resource("/v1/new_endpoint") class getList(@SerialName("my_parameter") val myParameter: kotlin.String)
}
  • In conclusion, that's why i suggest to add @SerialName("{{baseName}}") just before the val {{paramName}} into the file Paths.kt.mustache. By doing that, the value will match exactly with what is it expected from the API contract (yaml).

Notes:

  • This could cause breaking change if developer are defined for instance my_parameter or my-parameter within the API contract because it mean currently their application if working with myParameter in production (camelCase). Even if it is wrong because it mean service does not match the contract... The workaround is simple and is just to ensure to set the parameter name correctly into the API contract. For instance, the exemple above, developer will have to change their API contract from my-parameter to myParameter for the parameter name. Which is a good deal because it fix in the same time the inconsistency between the service delivered (endpoint) and the API contract they provide.
  • Currently, i suggested the change for main/resources/kotlin-server/libraries/ktor2/Paths.kt.mustache because i am using it for my project, but i guess we could provide the same for main/resources/kotlin-server/libraries/ktor/Paths.kt.mustache but i do not have enough experiences with Ktor to ensure that.

Summary by cubic

Add @SerialName("baseName") to parameters in generated Ktor 2 Paths resources to ensure path/query names follow the OpenAPI spec even when Kotlin property names differ. This fixes name mismatches with kotlinx.serialization during routing and URL building.

  • Bug Fixes
    • Adds @SerialName("{{baseName}}") to all parameters in Ktor 2 @Resource classes.
    • Fixes mismatched path/query names when Kotlin property names differ (e.g., reserved words, casing).
    • Regenerates samples/docs: Kotlin server now shows the annotations; C# petstore sample adds petstore_auth2 and updates tests to use multiple OAuth tokens.

Written for commit db5c81f. 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 1 file


Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

@kdefives kdefives changed the title draft: Add @SerialName annotation to parameter in Paths.kt.mustache Add @SerialName annotation to parameter in Paths.kt.mustache Mar 27, 2026
@kdefives
Copy link
Copy Markdown
Author

kdefives commented Mar 27, 2026

@karismann
@Zomzog
@andrewemery
@4brunu
@stefankoppier
@e5l
@dennisameling

What do you think about this suggestion?

@kdefives kdefives changed the title Add @SerialName annotation to parameter in Paths.kt.mustache Fix inconsistency between openapi contract and the generated code for URL parameters (Kotlin) Mar 27, 2026
@4brunu
Copy link
Copy Markdown
Contributor

4brunu commented Mar 27, 2026

Can you run the following commands and commit the changes? Thanks

./mvnw clean package || exit
./bin/generate-samples.sh ./bin/configs/*.yaml || exit
./bin/utils/export_docs_generators.sh || exit

@kdefives
Copy link
Copy Markdown
Author

Can you run the following commands and commit the changes? Thanks

./mvnw clean package || exit
./bin/generate-samples.sh ./bin/configs/*.yaml || exit
./bin/utils/export_docs_generators.sh || exit

Done

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.

1 issue found across 5 files (changes from recent commits).

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="samples/client/petstore/csharp/generichost/latest/UseDateTimeOffset/src/Org.OpenAPITools/Api/PetApi.cs">

<violation number="1" location="samples/client/petstore/csharp/generichost/latest/UseDateTimeOffset/src/Org.OpenAPITools/Api/PetApi.cs:852">
P2: AddPetAsync applies OAuth twice, retrieving and adding a second token/header, unlike other operations. This redundant OAuth call is likely unintended and can cause duplicate/overwritten auth headers and unnecessary rate-limit tracking.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

oauthTokenLocalVar1.UseInHeader(httpRequestMessageLocalVar, "");

HttpSignatureToken httpSignatureTokenLocalVar2 = (HttpSignatureToken) await HttpSignatureTokenProvider.GetAsync(cancellation: cancellationToken).ConfigureAwait(false);
OAuthToken oauthTokenLocalVar2 = (OAuthToken) await OauthTokenProvider.GetAsync(cancellation: cancellationToken).ConfigureAwait(false);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 30, 2026

Choose a reason for hiding this comment

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

P2: AddPetAsync applies OAuth twice, retrieving and adding a second token/header, unlike other operations. This redundant OAuth call is likely unintended and can cause duplicate/overwritten auth headers and unnecessary rate-limit tracking.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/csharp/generichost/latest/UseDateTimeOffset/src/Org.OpenAPITools/Api/PetApi.cs, line 852:

<comment>AddPetAsync applies OAuth twice, retrieving and adding a second token/header, unlike other operations. This redundant OAuth call is likely unintended and can cause duplicate/overwritten auth headers and unnecessary rate-limit tracking.</comment>

<file context>
@@ -849,14 +849,20 @@ public async Task<IAddPetApiResponse> AddPetAsync(Pet pet, System.Threading.Canc
                     oauthTokenLocalVar1.UseInHeader(httpRequestMessageLocalVar, "");
 
-                    HttpSignatureToken httpSignatureTokenLocalVar2 = (HttpSignatureToken) await HttpSignatureTokenProvider.GetAsync(cancellation: cancellationToken).ConfigureAwait(false);
+                    OAuthToken oauthTokenLocalVar2 = (OAuthToken) await OauthTokenProvider.GetAsync(cancellation: cancellationToken).ConfigureAwait(false);
 
-                    tokenBaseLocalVars.Add(httpSignatureTokenLocalVar2);
</file context>
Fix with Cubic

Copy link
Copy Markdown
Author

@kdefives kdefives Mar 30, 2026

Choose a reason for hiding this comment

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

This code has been changed by those cli execution:

./mvnw clean package
./bin/generate-samples.sh ./bin/configs/*.yaml
./bin/utils/export_docs_generators.sh

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.

3 participants