swagger-codegen 不会生成查询参数对象
swagger-codegen wont generate query parameter objects
我尝试根据来自 loopback4 的 openapi 规范生成一个 typescript-angular sdk,但是 swagger-codegen 一直忽略我的查询参数对象。
在下面的规范中,您会看到路径 GET /plans 可以有一个过滤器查询参数。
在生成的 class 中,生成的方法 planControllerFind(?:, observe: ...)
仅将 ?:
作为第一个参数而不是 planControllerFind(filter?: FilterClass, observe: ...)
我尝试了一些不同的规范结构,还尝试了 swagger-codegen 的不同版本(3.0.11、3.0.16、3.0.18),但似乎没有任何效果。在线版本还会生成不完整的代码。
谁能给我提示?
代码是通过以下方式生成的:
swagger-codegen generate -i http://localhost:3000/explorer/openapi.json -l typescript-angular -o app/src/app/core/lb4-sdk -c ./swagger-sdk.options.json
其中 /swagger-sdk.options.json
文件如下所示:
{
"npmName": "@ilem0n/ng-budget-api",
"npmVersion": "0.0.1",
"snapshot": true,
"ngVersion": "5.0.0"
}
这是我从 loopback4 生成的规范:
openapi: 3.0.0
info:
title: ngbm-api - NGBM API v1.0
version: 1.0.0
contact: {}
paths:
/plans:
post:
x-controller-name: PlanController
x-operation-name: create
tags:
- PlanController
responses:
'200':
description: User model instance
content:
application/json:
schema:
$ref: '#/components/schemas/Plan'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PlanNew'
operationId: PlanController.create
get:
x-controller-name: PlanController
x-operation-name: find
tags:
- PlanController
responses:
'200':
description: Array of User has many Plan
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Plan'
parameters:
- name: filter
in: query
content:
application/json:
schema:
type: object
title: Plan.Filter
properties:
offset:
type: integer
minimum: 0
limit:
type: integer
minimum: 1
example: 100
skip:
type: integer
minimum: 0
order:
type: array
items:
type: string
where:
title: Plan.WhereFilter
type: object
additionalProperties: true
fields:
title: Plan.Fields
type: object
properties:
id:
type: boolean
name:
type: boolean
ownerId:
type: boolean
additionalProperties: false
include:
title: Plan.IncludeFilter
type: array
items:
title: Plan.IncludeFilter.Items
type: object
properties:
relation:
type: string
scope:
properties:
offset:
type: integer
minimum: 0
limit:
type: integer
minimum: 1
example: 100
skip:
type: integer
minimum: 0
order:
type: array
items:
type: string
where:
type: object
additionalProperties: true
fields:
type: object
properties: {}
additionalProperties: true
additionalProperties: false
title: Plan.ScopeFilter
additionalProperties: false
operationId: PlanController.find
/users/login:
post:
x-controller-name: UserController
x-operation-name: login
tags:
- UserController
responses:
'200':
description: Auth & User data
content:
application/json:
schema:
$ref: '#/components/schemas/Auth'
requestBody:
description: The input of login function
required: true
content:
application/json:
schema:
title: Credentials
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
minLength: 8
operationId: UserController.login
/users/me:
get:
x-controller-name: UserController
x-operation-name: getUserData
tags:
- UserController
security:
- name:
- Bearer
responses:
'200':
description: Current user data
content:
application/json:
schema:
title: User
type: object
required:
- id
- name
- email
properties:
id:
type: string
name:
type: string
email:
type: string
operationId: UserController.getUserData
/users:
post:
x-controller-name: UserController
x-operation-name: create
tags:
- UserController
responses:
'200':
description: User model instance
content:
application/json:
schema:
title: User
type: object
required:
- id
- name
- email
properties:
id:
type: string
name:
type: string
email:
type: string
requestBody:
description: The input of register function
required: true
content:
application/json:
schema:
title: NewUser
type: object
required:
- name
- email
- password
properties:
name:
type: string
minLength: 3
email:
type: string
format: email
password:
type: string
minLength: 8
operationId: UserController.create
servers:
- url: /
components:
schemas:
Plan:
title: Plan
description: '(Schema options: { title: ''Plan'', exclude: [ ''ownerId'' ] })'
properties:
id:
type: string
name:
type: string
required:
- name
additionalProperties: false
PlanNew:
title: PlanNew
description: '(Schema options: { title: ''PlanNew'', exclude: [ ''id'', ''ownerId'' ] })'
properties:
name:
type: string
required:
- name
additionalProperties: false
Auth:
title: Auth
properties:
token:
type: string
expiresAt:
type: number
user:
type: object
required:
- token
- expiresAt
- user
additionalProperties: false
从这个规范中我得到了 planController 的以下 class:
/**
* ngbm-api - NGBM API v1.0
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*//* tslint:disable:no-unused-variable member-ordering */
import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent } from '@angular/common/http';
import { CustomHttpUrlEncodingCodec } from '../encoder';
import { Observable } from 'rxjs/Observable';
import { Plan } from '../model/plan';
import { PlanNew } from '../model/planNew';
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';
@Injectable()
export class PlanControllerService {
protected basePath = 'http://localhost:3000/';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();
constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
if (basePath) {
this.basePath = basePath;
}
if (configuration) {
this.configuration = configuration;
this.basePath = basePath || configuration.basePath || this.basePath;
}
}
/**
* @param consumes string[] mime-types
* @return true: consumes contains 'multipart/form-data', false: otherwise
*/
private canConsumeForm(consumes: string[]): boolean {
const form = 'multipart/form-data';
for (const consume of consumes) {
if (form === consume) {
return true;
}
}
return false;
}
/**
*
*
* @param body
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public planControllerCreate(body?: PlanNew, observe?: 'body', reportProgress?: boolean): Observable<Plan>;
public planControllerCreate(body?: PlanNew, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Plan>>;
public planControllerCreate(body?: PlanNew, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Plan>>;
public planControllerCreate(body?: PlanNew, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
let headers = this.defaultHeaders;
// to determine the Accept header
let httpHeaderAccepts: string[] = [
'application/json'
];
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
if (httpHeaderAcceptSelected != undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
// to determine the Content-Type header
const consumes: string[] = [
'application/json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected != undefined) {
headers = headers.set('Content-Type', httpContentTypeSelected);
}
return this.httpClient.request<Plan>('post',`${this.basePath}/plans`,
{
body: body,
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress
}
);
}
/**
*
*
* @param
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public planControllerFind(?: , observe?: 'body', reportProgress?: boolean): Observable<Array<Plan>>;
public planControllerFind(?: , observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<Plan>>>;
public planControllerFind(?: , observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<Plan>>>;
public planControllerFind(?: , observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
let queryParameters = new HttpParams({encoder: new CustomHttpUrlEncodingCodec()});
if ( !== undefined && !== null) {
queryParameters = queryParameters.set('filter', <any>);
}
let headers = this.defaultHeaders;
// to determine the Accept header
let httpHeaderAccepts: string[] = [
'application/json'
];
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
if (httpHeaderAcceptSelected != undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
// to determine the Content-Type header
const consumes: string[] = [
];
return this.httpClient.request<Array<Plan>>('get',`${this.basePath}/plans`,
{
params: queryParameters,
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress
}
);
}
}
我在 swagger-api/swagger-codegen https://github.com/swagger-api/swagger-codegen/issues/10158 提出了一个问题,但还没有找到解决方案。
我已经切换到 https://github.com/OpenAPITools/openapi-generator,它解决了我的问题。其实没问题。
我尝试根据来自 loopback4 的 openapi 规范生成一个 typescript-angular sdk,但是 swagger-codegen 一直忽略我的查询参数对象。
在下面的规范中,您会看到路径 GET /plans 可以有一个过滤器查询参数。
在生成的 class 中,生成的方法 planControllerFind(?:, observe: ...)
仅将 ?:
作为第一个参数而不是 planControllerFind(filter?: FilterClass, observe: ...)
我尝试了一些不同的规范结构,还尝试了 swagger-codegen 的不同版本(3.0.11、3.0.16、3.0.18),但似乎没有任何效果。在线版本还会生成不完整的代码。
谁能给我提示?
代码是通过以下方式生成的:
swagger-codegen generate -i http://localhost:3000/explorer/openapi.json -l typescript-angular -o app/src/app/core/lb4-sdk -c ./swagger-sdk.options.json
其中 /swagger-sdk.options.json
文件如下所示:
{
"npmName": "@ilem0n/ng-budget-api",
"npmVersion": "0.0.1",
"snapshot": true,
"ngVersion": "5.0.0"
}
这是我从 loopback4 生成的规范:
openapi: 3.0.0
info:
title: ngbm-api - NGBM API v1.0
version: 1.0.0
contact: {}
paths:
/plans:
post:
x-controller-name: PlanController
x-operation-name: create
tags:
- PlanController
responses:
'200':
description: User model instance
content:
application/json:
schema:
$ref: '#/components/schemas/Plan'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PlanNew'
operationId: PlanController.create
get:
x-controller-name: PlanController
x-operation-name: find
tags:
- PlanController
responses:
'200':
description: Array of User has many Plan
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Plan'
parameters:
- name: filter
in: query
content:
application/json:
schema:
type: object
title: Plan.Filter
properties:
offset:
type: integer
minimum: 0
limit:
type: integer
minimum: 1
example: 100
skip:
type: integer
minimum: 0
order:
type: array
items:
type: string
where:
title: Plan.WhereFilter
type: object
additionalProperties: true
fields:
title: Plan.Fields
type: object
properties:
id:
type: boolean
name:
type: boolean
ownerId:
type: boolean
additionalProperties: false
include:
title: Plan.IncludeFilter
type: array
items:
title: Plan.IncludeFilter.Items
type: object
properties:
relation:
type: string
scope:
properties:
offset:
type: integer
minimum: 0
limit:
type: integer
minimum: 1
example: 100
skip:
type: integer
minimum: 0
order:
type: array
items:
type: string
where:
type: object
additionalProperties: true
fields:
type: object
properties: {}
additionalProperties: true
additionalProperties: false
title: Plan.ScopeFilter
additionalProperties: false
operationId: PlanController.find
/users/login:
post:
x-controller-name: UserController
x-operation-name: login
tags:
- UserController
responses:
'200':
description: Auth & User data
content:
application/json:
schema:
$ref: '#/components/schemas/Auth'
requestBody:
description: The input of login function
required: true
content:
application/json:
schema:
title: Credentials
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
minLength: 8
operationId: UserController.login
/users/me:
get:
x-controller-name: UserController
x-operation-name: getUserData
tags:
- UserController
security:
- name:
- Bearer
responses:
'200':
description: Current user data
content:
application/json:
schema:
title: User
type: object
required:
- id
- name
- email
properties:
id:
type: string
name:
type: string
email:
type: string
operationId: UserController.getUserData
/users:
post:
x-controller-name: UserController
x-operation-name: create
tags:
- UserController
responses:
'200':
description: User model instance
content:
application/json:
schema:
title: User
type: object
required:
- id
- name
- email
properties:
id:
type: string
name:
type: string
email:
type: string
requestBody:
description: The input of register function
required: true
content:
application/json:
schema:
title: NewUser
type: object
required:
- name
- email
- password
properties:
name:
type: string
minLength: 3
email:
type: string
format: email
password:
type: string
minLength: 8
operationId: UserController.create
servers:
- url: /
components:
schemas:
Plan:
title: Plan
description: '(Schema options: { title: ''Plan'', exclude: [ ''ownerId'' ] })'
properties:
id:
type: string
name:
type: string
required:
- name
additionalProperties: false
PlanNew:
title: PlanNew
description: '(Schema options: { title: ''PlanNew'', exclude: [ ''id'', ''ownerId'' ] })'
properties:
name:
type: string
required:
- name
additionalProperties: false
Auth:
title: Auth
properties:
token:
type: string
expiresAt:
type: number
user:
type: object
required:
- token
- expiresAt
- user
additionalProperties: false
从这个规范中我得到了 planController 的以下 class:
/**
* ngbm-api - NGBM API v1.0
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*//* tslint:disable:no-unused-variable member-ordering */
import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent } from '@angular/common/http';
import { CustomHttpUrlEncodingCodec } from '../encoder';
import { Observable } from 'rxjs/Observable';
import { Plan } from '../model/plan';
import { PlanNew } from '../model/planNew';
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';
@Injectable()
export class PlanControllerService {
protected basePath = 'http://localhost:3000/';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();
constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
if (basePath) {
this.basePath = basePath;
}
if (configuration) {
this.configuration = configuration;
this.basePath = basePath || configuration.basePath || this.basePath;
}
}
/**
* @param consumes string[] mime-types
* @return true: consumes contains 'multipart/form-data', false: otherwise
*/
private canConsumeForm(consumes: string[]): boolean {
const form = 'multipart/form-data';
for (const consume of consumes) {
if (form === consume) {
return true;
}
}
return false;
}
/**
*
*
* @param body
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public planControllerCreate(body?: PlanNew, observe?: 'body', reportProgress?: boolean): Observable<Plan>;
public planControllerCreate(body?: PlanNew, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Plan>>;
public planControllerCreate(body?: PlanNew, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Plan>>;
public planControllerCreate(body?: PlanNew, observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
let headers = this.defaultHeaders;
// to determine the Accept header
let httpHeaderAccepts: string[] = [
'application/json'
];
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
if (httpHeaderAcceptSelected != undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
// to determine the Content-Type header
const consumes: string[] = [
'application/json'
];
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
if (httpContentTypeSelected != undefined) {
headers = headers.set('Content-Type', httpContentTypeSelected);
}
return this.httpClient.request<Plan>('post',`${this.basePath}/plans`,
{
body: body,
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress
}
);
}
/**
*
*
* @param
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public planControllerFind(?: , observe?: 'body', reportProgress?: boolean): Observable<Array<Plan>>;
public planControllerFind(?: , observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<Plan>>>;
public planControllerFind(?: , observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<Plan>>>;
public planControllerFind(?: , observe: any = 'body', reportProgress: boolean = false ): Observable<any> {
let queryParameters = new HttpParams({encoder: new CustomHttpUrlEncodingCodec()});
if ( !== undefined && !== null) {
queryParameters = queryParameters.set('filter', <any>);
}
let headers = this.defaultHeaders;
// to determine the Accept header
let httpHeaderAccepts: string[] = [
'application/json'
];
const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
if (httpHeaderAcceptSelected != undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
// to determine the Content-Type header
const consumes: string[] = [
];
return this.httpClient.request<Array<Plan>>('get',`${this.basePath}/plans`,
{
params: queryParameters,
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress
}
);
}
}
我在 swagger-api/swagger-codegen https://github.com/swagger-api/swagger-codegen/issues/10158 提出了一个问题,但还没有找到解决方案。
我已经切换到 https://github.com/OpenAPITools/openapi-generator,它解决了我的问题。其实没问题。