Is your feature request related to a problem? Please describe.
At present, typescript-angular only supports arrays and simple types (string,
number, Date) as query parameters. However, when you use openapi-generator in
conjuction with springdoc and (java) spring, you wish
to have support for objects as query parameters as well.
In spring-data, there is REST support for an idea called
Pageable. This would
be the openapi schema for it:
"Pageable": {
"nullable": false,
"type": "object",
"required": [
"size",
"page"
],
"properties": {
"size": {
"format": "int32",
"type": "integer"
},
"sort": {"$ref": "#/components/schemas/Sort"},
"page": {
"format": "int32",
"type": "integer"
}
}
},
"Sort": {
"nullable": false,
"type": "array",
"items": {"type": "string"}
},
The items of Sort are the names of the properties to sort the data with.
Optionally, there could be a sort direction (ASC, DESC) appended like in
ansatz,DESC. The comma (,) should not be urlencoded.
What I want is sane support for Pageable and other objects.
Describe the solution you'd like
Lets think about a (GET) REST endpoint that takes an Pageable and a map
with parameters as query parameters. openapi-generator will emits something
like:
public getAllAnsatz(pageable: Pageable, map: { [key: string]: Array<string>; }, observe?: 'body', reportProgress?: boolean): Observable<Array<AnsatzDTO>>;
public getAllAnsatz(pageable: Pageable, map: { [key: string]: Array<string>; }, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<AnsatzDTO>>>;
public getAllAnsatz(pageable: Pageable, map: { [key: string]: Array<string>; }, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<AnsatzDTO>>>;
public getAllAnsatz(pageable: Pageable, map: { [key: string]: Array<string>; }, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
if (pageable === null || pageable === undefined) {
throw new Error('Required parameter pageable was null or undefined when calling getAllAnsatzfreigabes.');
}
if (map === null || map === undefined) {
throw new Error('Required parameter map was null or undefined when calling getAllAnsatzfreigabes.');
}
let queryParameters = new HttpParams({encoder: this.encoder});
if (pageable !== undefined && pageable !== null) {
queryParameters = queryParameters.set('pageable', <any>pageable);
}
if (map !== undefined && map !== null) {
queryParameters = queryParameters.set('map', <any>map);
}
Certainly, this will not lead to the desired result, as implicit toString is called on pageable
and map.
The idea is to have a method that will act according to the dynamic type of the variable
that should be added to queryParameters:
let queryParameters = new HttpParams({encoder: this.encoder});
if (pageable !== undefined && pageable !== null) {
queryParameters = this.addToHttpParams(queryParameters, <any>pageable, 'pageable')
}
if (map !== undefined && map !== null) {
queryParameters = this.addToHttpParams(queryParameters, <any>map, 'map')
}
Proposed implementation of addToHttpParams
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
if (typeof value === "object") {
httpParams = this.addToHttpParams1(httpParams, value);
} else {
httpParams = this.addToHttpParams1(httpParams, value, key);
}
return httpParams;
}
private addToHttpParams1(httpParams: HttpParams, value: any, key?: string): HttpParams {
if (typeof value === "object") {
if (this.isArrayLike(value)) {
(value as []).forEach( elem => httpParams = this.addToHttpParams1(httpParams, elem, key));
} else if (value instanceof Date) {
if (key != null) {
httpParams = httpParams.append(key,
(value as Date).toISOString().substr(0, 10));
} else {
throw Error("key may not be null if value is Date");
}
} else {
Object.keys(value).forEach( k => httpParams = this.addToHttpParams1(
httpParams, value[k], key != null ? `${key}.${k}` : k));
}
} else if (key != null) {
httpParams = httpParams.append(key, value);
} else {
throw Error("key may not be null if value is not object or array");
}
return httpParams;
}
private isArrayLike(obj: any): boolean {
return (Array.isArray(obj) ||
typeof obj === "object" &&
typeof (obj.length) === "number" &&
(obj.length === 0 ||
(obj.length > 0 && (obj.length - 1) in obj))
);
}
The implementation will flatten the top level object to properties, but nested
are added with . Syntax to the key (like in
toplevelProperty.propertyOfNestedObject). Arrays and simple types are treated
like before (no change). The advantage of the new solution is that REST endpoints
from spring-data are supported out of the box.
Is your feature request related to a problem? Please describe.
At present, typescript-angular only supports arrays and simple types (string,
number, Date) as query parameters. However, when you use openapi-generator in
conjuction with springdoc and (java) spring, you wish
to have support for objects as query parameters as well.
In spring-data, there is REST support for an idea called
Pageable. This wouldbe the openapi schema for it:
The
itemsof Sort are the names of the properties to sort the data with.Optionally, there could be a sort direction (ASC, DESC) appended like in
ansatz,DESC. The comma (,) should not be urlencoded.What I want is sane support for
Pageableand other objects.Describe the solution you'd like
Lets think about a (GET) REST endpoint that takes an
Pageableand a mapwith parameters as query parameters.
openapi-generatorwill emits somethinglike:
Certainly, this will not lead to the desired result, as implicit
toStringis called onpageableand
map.The idea is to have a method that will act according to the dynamic type of the variable
that should be added to
queryParameters:Proposed implementation of
addToHttpParamsThe implementation will flatten the top level
objectto properties, but nestedare added with
.Syntax to the key (like intoplevelProperty.propertyOfNestedObject). Arrays and simple types are treatedlike before (no change). The advantage of the new solution is that REST endpoints
from spring-data are supported out of the box.