diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/queryParams.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/queryParams.mustache index 4076c1140c83..978fde0d2ea2 100644 --- a/modules/openapi-generator/src/main/resources/typescript-angular/queryParams.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-angular/queryParams.mustache @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular-v20/builds/query-param-deep-object/query.params.ts b/samples/client/others/typescript-angular-v20/builds/query-param-deep-object/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular-v20/builds/query-param-deep-object/query.params.ts +++ b/samples/client/others/typescript-angular-v20/builds/query-param-deep-object/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts b/samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts +++ b/samples/client/others/typescript-angular-v20/builds/query-param-form-dot/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular-v20/builds/query-param-form/query.params.ts b/samples/client/others/typescript-angular-v20/builds/query-param-form/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular-v20/builds/query-param-form/query.params.ts +++ b/samples/client/others/typescript-angular-v20/builds/query-param-form/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular-v20/builds/query-param-json/query.params.ts b/samples/client/others/typescript-angular-v20/builds/query-param-json/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular-v20/builds/query-param-json/query.params.ts +++ b/samples/client/others/typescript-angular-v20/builds/query-param-json/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular-v20/projects/app/src/api.query_param_form.spec.ts b/samples/client/others/typescript-angular-v20/projects/app/src/api.query_param_form.spec.ts index d0994e2a8822..6397a53f753a 100644 --- a/samples/client/others/typescript-angular-v20/projects/app/src/api.query_param_form.spec.ts +++ b/samples/client/others/typescript-angular-v20/projects/app/src/api.query_param_form.spec.ts @@ -7,6 +7,11 @@ import {DefaultService, Filter, provideApi} from '@swagger/typescript-angular-qu const ids: number[] = [4, 5]; const filter: Filter = {name: 'John', age: 37, nicknames: ['Joe', 'Joey']}; const filterWithSpecialCharacters: Filter = {name: 'Éléonore &,|+', age: 42, nicknames: ['Elé', 'Ellie']}; +const filterWithUndefined: Filter = {name: 'John', age: undefined, nicknames: ['Joe']}; +const filterAllUndefined: Filter = {name: undefined, age: undefined, nicknames: undefined}; +const filterWithNullItems = {name: 'John', nicknames: ['Joe', null, undefined]} as unknown as Filter; +const filterWithOnlyNullItems = {name: 'John', nicknames: [null, undefined], age: 37} as unknown as Filter; +const filterWithEmptyArray: Filter = {name: 'John', nicknames: [], age: 37}; const country: string = "Belgium"; const tags: Set = new Set(['a', 'b']); @@ -75,6 +80,13 @@ describe('Form Query Param testing', () => { expect(req.request.method).toEqual('GET'); }); + it('should separate the query parameter with ampersands (object with undefined field)', async () => { + service.searchExplode(undefined, filterWithUndefined, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_explode?name=John&nicknames=Joe'); + expect(req.request.method).toEqual('GET'); + }); + it('should separate the query parameter with ampersands (simple only)', async () => { service.searchExplode(undefined, undefined, country).subscribe(); const req = httpTesting.expectOne('http://localhost/search_explode?country=Belgium'); @@ -133,6 +145,41 @@ describe('Form Query Param testing', () => { expect(req.request.method).toEqual('GET'); }); + it('should separate the query parameter with comma (object with undefined field)', async () => { + service.searchNotExplode(undefined, filterWithUndefined, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_not_explode?filter=name,John,nicknames,Joe'); + expect(req.request.method).toEqual('GET'); + }); + + it('should separate the query parameter with comma (object with all fields undefined)', async () => { + service.searchNotExplode(undefined, filterAllUndefined, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_not_explode?filter='); + expect(req.request.method).toEqual('GET'); + }); + + it('should separate the query parameter with comma (object with null array items)', async () => { + service.searchNotExplode(undefined, filterWithNullItems, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_not_explode?filter=name,John,nicknames,Joe'); + expect(req.request.method).toEqual('GET'); + }); + + it('should separate the query parameter with comma (object with only null array items)', async () => { + service.searchNotExplode(undefined, filterWithOnlyNullItems, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_not_explode?filter=name,John,age,37'); + expect(req.request.method).toEqual('GET'); + }); + + it('should separate the query parameter with comma (object with empty array field)', async () => { + service.searchNotExplode(undefined, filterWithEmptyArray, undefined).subscribe(); + + const req = httpTesting.expectOne('http://localhost/search_not_explode?filter=name,John,age,37'); + expect(req.request.method).toEqual('GET'); + }); + it('should separate the query parameter with comma (simple only)', async () => { service.searchNotExplode(undefined, undefined, country).subscribe(); const req = httpTesting.expectOne('http://localhost/search_not_explode?country=Belgium'); diff --git a/samples/client/others/typescript-angular/builds/composed-schemas-tagged-unions/query.params.ts b/samples/client/others/typescript-angular/builds/composed-schemas-tagged-unions/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular/builds/composed-schemas-tagged-unions/query.params.ts +++ b/samples/client/others/typescript-angular/builds/composed-schemas-tagged-unions/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/others/typescript-angular/builds/composed-schemas/query.params.ts b/samples/client/others/typescript-angular/builds/composed-schemas/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/others/typescript-angular/builds/composed-schemas/query.params.ts +++ b/samples/client/others/typescript-angular/builds/composed-schemas/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v18-provided-in-root/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v18-provided-in-root/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v18-provided-in-root/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v18-provided-in-root/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v19-provided-in-root/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v19-provided-in-root/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v19-provided-in-root/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v19-provided-in-root/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v19-with-angular-dependency-params/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v19-with-angular-dependency-params/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v19-with-angular-dependency-params/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v19-with-angular-dependency-params/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v19/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v19/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v19/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v19/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v20-provided-in-root/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v20-provided-in-root/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v20-provided-in-root/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v20-provided-in-root/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v20/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v20/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v20/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v20/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v21-provided-in-root/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v21-provided-in-root/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v21-provided-in-root/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v21-provided-in-root/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v21/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v21/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v21/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v21/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/with-http-resource/query.params.ts b/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/with-http-resource/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/with-http-resource/query.params.ts +++ b/samples/client/petstore/typescript-angular-v22-provided-in-root/builds/with-http-resource/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } } diff --git a/samples/client/petstore/typescript-angular-v22/builds/default/query.params.ts b/samples/client/petstore/typescript-angular-v22/builds/default/query.params.ts index 4076c1140c83..978fde0d2ea2 100644 --- a/samples/client/petstore/typescript-angular-v22/builds/default/query.params.ts +++ b/samples/client/petstore/typescript-angular-v22/builds/default/query.params.ts @@ -137,14 +137,20 @@ export function concatHttpParamsObject(httpParams: OpenApiHttpParams, key: strin let keyAndValues: string[] = []; for (const k in item) { - keyAndValues.push(k); - const value = item[k]; + if (value === null || value === undefined) { + continue; + } + if (Array.isArray(value)) { - keyAndValues.push(...value.map(convertToString)); + const items = value.filter(v => v !== null && v !== undefined); + + if (items.length > 0) { + keyAndValues.push(k, ...items.map(convertToString)); + } } else { - keyAndValues.push(convertToString(value)); + keyAndValues.push(k, convertToString(value)); } }