Conversation
Add useDotNotationForFormObjects with a false default so standard form serialization remains unchanged. Preserve parameter-prefixed property paths when enabled, document the server-specific convention, and add generator and runtime regression coverage with a generated sample.
There was a problem hiding this comment.
5 issues found across 32 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/typescript-angular/README.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/typescript-angular/README.mustache:186">
P3: The new dot-notation documentation is only added to README.mustache, which is used only when ngVersion >= 17. Clients generated with pre-v17 templates (README_beforeV17.mustache) still get the `useDotNotationForFormObjects` behavior from the shared api.base.service.mustache, but their README.md never documents it. Add the equivalent section to README_beforeV17.mustache so both template variants document the option.</violation>
</file>
<file name="samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts">
<violation number="1" location="samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts:92">
P2: When an exploded parameter has multiple values, `toString()` joins the array with commas instead of emitting repeated key/value pairs. Iterate array values and add one `key=value` entry per value.</violation>
<violation number="2" location="samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts:104">
P2: A query parameter named `__proto__` is silently lost because `toRecord()` writes encoded keys into a normal object. Use a null-prototype record so all valid parameter names serialize safely.</violation>
</file>
<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java">
<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java:495">
P3: In the enabled (`true`) branch, the test asserts only `contains` for the dot-notation template, but the disabled branch also asserts `doesNotContain` for the opposite variant. Add the symmetric negative assertion so a regression that emits both the plain `k` and the `` `${key}.${k}` `` form fails the test.</violation>
</file>
<file name="samples/client/others/typescript-angular-v20/builds/query-param-form-dot/README.md">
<violation number="1" location="samples/client/others/typescript-angular-v20/builds/query-param-form-dot/README.md:192">
P3: The README advertises nested dot-notation (`filter.name.contains=Alice`), but the sample spec (`query-param-form.yaml`) defines `Filter` with only flat properties, so the generated sample never exercises the recursive nested-object branch of `addToHttpParams`. Add a nested object property (e.g. `name: { contains: string }`) to the `filter` param so the documented behavior and the recursion in the generated code are actually covered by the sample build.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| * - If a parameter has multiple values, returns a readonly array of values. | ||
| */ | ||
| toRecord(): Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> { | ||
| const parts: Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> = {}; |
There was a problem hiding this comment.
P2: A query parameter named __proto__ is silently lost because toRecord() writes encoded keys into a normal object. Use a null-prototype record so all valid parameter names serialize safely.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts, line 104:
<comment>A query parameter named `__proto__` is silently lost because `toRecord()` writes encoded keys into a normal object. Use a null-prototype record so all valid parameter names serialize safely.</comment>
<file context>
@@ -0,0 +1,160 @@
+ * - If a parameter has multiple values, returns a readonly array of values.
+ */
+ toRecord(): Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> {
+ const parts: Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> = {};
+
+ for (const [key, entry] of this.params.entries()) {
</file context>
| const parts: Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> = {}; | |
| const parts: Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>> = Object.create(null); |
| const parts: string[] = []; | ||
|
|
||
| for (const key in records) { | ||
| parts.push(`${key}=${records[key]}`); |
There was a problem hiding this comment.
P2: When an exploded parameter has multiple values, toString() joins the array with commas instead of emitting repeated key/value pairs. Iterate array values and add one key=value entry per value.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts, line 92:
<comment>When an exploded parameter has multiple values, `toString()` joins the array with commas instead of emitting repeated key/value pairs. Iterate array values and add one `key=value` entry per value.</comment>
<file context>
@@ -0,0 +1,160 @@
+ const parts: string[] = [];
+
+ for (const key in records) {
+ parts.push(`${key}=${records[key]}`);
+ }
+
</file context>
| parts.push(`${key}=${records[key]}`); | |
| const value = records[key]; | |
| if (Array.isArray(value)) { | |
| value.forEach((item) => parts.push(`${key}=${item}`)); | |
| } else { | |
| parts.push(`${key}=${value}`); | |
| } |
| [parameter-locations-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-locations | ||
| [style-values-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#style-values | ||
| [@honoluluhenk/http-param-expander]: https://www.npmjs.com/package/@honoluluhenk/http-param-expander | ||
| {{#useDotNotationForFormObjects}} |
There was a problem hiding this comment.
P3: The new dot-notation documentation is only added to README.mustache, which is used only when ngVersion >= 17. Clients generated with pre-v17 templates (README_beforeV17.mustache) still get the useDotNotationForFormObjects behavior from the shared api.base.service.mustache, but their README.md never documents it. Add the equivalent section to README_beforeV17.mustache so both template variants document the option.
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/typescript-angular/README.mustache, line 186:
<comment>The new dot-notation documentation is only added to README.mustache, which is used only when ngVersion >= 17. Clients generated with pre-v17 templates (README_beforeV17.mustache) still get the `useDotNotationForFormObjects` behavior from the shared api.base.service.mustache, but their README.md never documents it. Add the equivalent section to README_beforeV17.mustache so both template variants document the option.</comment>
<file context>
@@ -183,3 +183,17 @@ new Configuration({
[parameter-locations-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-locations
[style-values-url]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#style-values
[@honoluluhenk/http-param-expander]: https://www.npmjs.com/package/@honoluluhenk/http-param-expander
+{{#useDotNotationForFormObjects}}
+
+## Form query object dot notation
</file context>
| new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); | ||
| String service = Files.readString(output.toPath().resolve("api.base.service.ts")); | ||
| if (Boolean.parseBoolean(String.valueOf(option))) { | ||
| assertThat(service).contains("this.addToHttpParams(httpParams, `${key}.${k}`, value[k], paramStyle, explode)"); |
There was a problem hiding this comment.
P3: In the enabled (true) branch, the test asserts only contains for the dot-notation template, but the disabled branch also asserts doesNotContain for the opposite variant. Add the symmetric negative assertion so a regression that emits both the plain k and the `${key}.${k}` form fails the test.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientCodegenTest.java, line 495:
<comment>In the enabled (`true`) branch, the test asserts only `contains` for the dot-notation template, but the disabled branch also asserts `doesNotContain` for the opposite variant. Add the symmetric negative assertion so a regression that emits both the plain `k` and the `` `${key}.${k}` `` form fails the test.</comment>
<file context>
@@ -477,6 +477,29 @@ public void testEnumAsConst() throws IOException {
+ new DefaultGenerator().opts(configurator.toClientOptInput()).generate();
+ String service = Files.readString(output.toPath().resolve("api.base.service.ts"));
+ if (Boolean.parseBoolean(String.valueOf(option))) {
+ assertThat(service).contains("this.addToHttpParams(httpParams, `${key}.${k}`, value[k], paramStyle, explode)");
+ } else {
+ assertThat(service).contains("this.addToHttpParams(httpParams, k, value[k], paramStyle, explode)");
</file context>
| assertThat(service).contains("this.addToHttpParams(httpParams, `${key}.${k}`, value[k], paramStyle, explode)"); | |
| assertThat(service).contains("this.addToHttpParams(httpParams, `${key}.${k}`, value[k], paramStyle, explode)"); | |
| assertThat(service).doesNotContain("this.addToHttpParams(httpParams, k, value[k], paramStyle, explode)"); |
| This client was generated with `useDotNotationForFormObjects=true`. For exploded | ||
| form query objects, property names include the parameter name and all parent | ||
| properties: `filter = { name: { contains: "Alice" } }` is serialized as | ||
| `filter.name.contains=Alice`. Primitive arrays and sets retain repeated keys, |
There was a problem hiding this comment.
P3: The README advertises nested dot-notation (filter.name.contains=Alice), but the sample spec (query-param-form.yaml) defines Filter with only flat properties, so the generated sample never exercises the recursive nested-object branch of addToHttpParams. Add a nested object property (e.g. name: { contains: string }) to the filter param so the documented behavior and the recursion in the generated code are actually covered by the sample build.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/typescript-angular-v20/builds/query-param-form-dot/README.md, line 192:
<comment>The README advertises nested dot-notation (`filter.name.contains=Alice`), but the sample spec (`query-param-form.yaml`) defines `Filter` with only flat properties, so the generated sample never exercises the recursive nested-object branch of `addToHttpParams`. Add a nested object property (e.g. `name: { contains: string }`) to the `filter` param so the documented behavior and the recursion in the generated code are actually covered by the sample build.</comment>
<file context>
@@ -0,0 +1,197 @@
+This client was generated with `useDotNotationForFormObjects=true`. For exploded
+form query objects, property names include the parameter name and all parent
+properties: `filter = { name: { contains: "Alice" } }` is serialized as
+`filter.name.contains=Alice`. Primitive arrays and sets retain repeated keys,
+for example `filter.ids=1&filter.ids=2`.
+
</file context>
Fixes #23895
Add useDotNotationForFormObjects with a false default so standard form serialization remains unchanged. Preserve parameter-prefixed property paths when enabled, document the server-specific convention, and add generator and runtime regression coverage with a generated sample.
This PR was AI generated! But looks quite good to me. Intention is to support .Net Query Param serialization style.
Summary by cubic
Adds an opt-in
useDotNotationForFormObjectsoption to the TypeScript Angular generator so exploded form query objects can be serialized with parameter-prefixed dot notation (e.g.,filter.name=Alice) for servers like .NET that require this convention.false, leaving standard OpenAPI form serialization unchanged.filter.first.id=1), and primitive arrays and sets keep repeated keys.Written for commit 713c536. Summary will update on new commits.