Java 生成不一致 类 的 OpenAPI Maven 插件
OpenAPI Maven Plugin for Java Generating Inconsistent Classes
我们正在使用 openapi-generator-maven-plugin 版本 5.0.1 生成我们的 APIs。我正在尝试指定一个包含 DTO 和文件的请求。
第一个奇怪的事情是生成的代码不使用 DTO,它基本上是扁平化字段,因此 API 期望指定每个字段。然而,我们并不是真的太在意这个问题,因为我们可以指定每个字段(尽管如果它按预期工作就好了)。
困扰我们的问题是为 API 和 API 委托生成的 classes 彼此不一致。生成的 API 将每个字段视为 String
。但是,API 代表将它们视为 Optional<String>
。因此,当我们尝试编译代码时,API 会出现编译错误,因为它正在将字符串传递给委托,而委托想要 Optional<String>
.
这是我们的 POM,以及相关的依赖项和插件配置:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
...
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.0.1</version>
<executions>
<execution>
<id>processor-Generate</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>
${project.basedir}/apis/innovation-ivp-inventory-accuracy-acl-api.yml
</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>${project.groupId}.inventory.accuracy.acl.api</apiPackage>
<modelPackage>${project.groupId}.inventory.accuracy.acl.dto</modelPackage>
<invokerPackage>${project.groupId}.inventory.accuracy.acl.api.handler</invokerPackage>
<supportingFilesToGenerate>ApiUtil.java,OpenAPIDocumentationConfig.java
</supportingFilesToGenerate>
<configOptions>
<useTags>true</useTags>
<dateLibrary>java8-localdatetime</dateLibrary>
<java8>true</java8>
<delegatePattern>true</delegatePattern>
<useBeanValidation>true</useBeanValidation>
<useOptional>true</useOptional>
<configPackage>${project.groupId}.inventory.accuracy.acl.api</configPackage>
</configOptions>
<output>${project.build.directory}/generated-sources</output>
</configuration>
</execution>
</executions>
</plugin>
这是我们的 OpenAPI 规范:
'/email':
post:
tags:
- email-service
summary: Email Service
operationId: sendEmail
requestBody:
required: true
content:
multipart/mixed:
schema:
allOf:
- $ref: '#/components/schemas/EmailRequestDTO'
- type: object
properties:
file:
type: string
format: binary
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/EmailResponseDTO'
components:
schemas:
EmailRequestDTO:
type: object
properties:
sendTo:
type: string
sentFrom:
type: string
subject:
type: string
content:
type: string
EmailResponseDTO:
type: object
properties:
status:
type: string
errorMessage:
type: string
这里是OpenAPI生成的APIclass(注意参数都是String):
public interface EmailServiceApi {
@ApiOperation(value = "Email Service", nickname = "sendEmail", notes = "", response = EmailResponseDTO.class, tags={ "email-service", })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = EmailResponseDTO.class) })
@PostMapping(
value = "/email",
produces = { "application/json" },
consumes = { "multipart/mixed" }
)
default ResponseEntity<EmailResponseDTO> sendEmail(@ApiParam(value = "") @Valid @RequestPart(value = "sendTo", required = false) String sendTo,@ApiParam(value = "") @Valid @RequestPart(value = "sentFrom", required = false) String sentFrom,@ApiParam(value = "") @Valid @RequestPart(value = "subject", required = false) String subject,@ApiParam(value = "") @Valid @RequestPart(value = "content", required = false) String content,@ApiParam(value = "") @Valid @RequestPart(value = "file", required = false) MultipartFile file) {
return getDelegate().sendEmail(sendTo, sentFrom, subject, content, file);
}
}
这里是OpenAPI生成的API委托class(注意参数都是可选的):
public interface EmailServiceApiDelegate {
default ResponseEntity<EmailResponseDTO> sendEmail(Optional<String> sendTo,
Optional<String> sentFrom,
Optional<String> subject,
Optional<String> content,
MultipartFile file) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"errorMessage\" : \"errorMessage\", \"status\" : \"status\" }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
使用 allOf
将列出的所有架构合并为一个。 EmailRequestDTO
的属性和内联定义对象的属性是作为参数而不是作为 DTO 生成的。参见 https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/#allof
如果您不希望生成可选字符串作为委托中的参数,请删除 useOptional
配置。参见 https://openapi-generator.tech/docs/generators/spring/
我们正在使用 openapi-generator-maven-plugin 版本 5.0.1 生成我们的 APIs。我正在尝试指定一个包含 DTO 和文件的请求。
第一个奇怪的事情是生成的代码不使用 DTO,它基本上是扁平化字段,因此 API 期望指定每个字段。然而,我们并不是真的太在意这个问题,因为我们可以指定每个字段(尽管如果它按预期工作就好了)。
困扰我们的问题是为 API 和 API 委托生成的 classes 彼此不一致。生成的 API 将每个字段视为 String
。但是,API 代表将它们视为 Optional<String>
。因此,当我们尝试编译代码时,API 会出现编译错误,因为它正在将字符串传递给委托,而委托想要 Optional<String>
.
这是我们的 POM,以及相关的依赖项和插件配置:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
...
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.0.1</version>
<executions>
<execution>
<id>processor-Generate</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>
${project.basedir}/apis/innovation-ivp-inventory-accuracy-acl-api.yml
</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>${project.groupId}.inventory.accuracy.acl.api</apiPackage>
<modelPackage>${project.groupId}.inventory.accuracy.acl.dto</modelPackage>
<invokerPackage>${project.groupId}.inventory.accuracy.acl.api.handler</invokerPackage>
<supportingFilesToGenerate>ApiUtil.java,OpenAPIDocumentationConfig.java
</supportingFilesToGenerate>
<configOptions>
<useTags>true</useTags>
<dateLibrary>java8-localdatetime</dateLibrary>
<java8>true</java8>
<delegatePattern>true</delegatePattern>
<useBeanValidation>true</useBeanValidation>
<useOptional>true</useOptional>
<configPackage>${project.groupId}.inventory.accuracy.acl.api</configPackage>
</configOptions>
<output>${project.build.directory}/generated-sources</output>
</configuration>
</execution>
</executions>
</plugin>
这是我们的 OpenAPI 规范:
'/email':
post:
tags:
- email-service
summary: Email Service
operationId: sendEmail
requestBody:
required: true
content:
multipart/mixed:
schema:
allOf:
- $ref: '#/components/schemas/EmailRequestDTO'
- type: object
properties:
file:
type: string
format: binary
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/EmailResponseDTO'
components:
schemas:
EmailRequestDTO:
type: object
properties:
sendTo:
type: string
sentFrom:
type: string
subject:
type: string
content:
type: string
EmailResponseDTO:
type: object
properties:
status:
type: string
errorMessage:
type: string
这里是OpenAPI生成的APIclass(注意参数都是String):
public interface EmailServiceApi {
@ApiOperation(value = "Email Service", nickname = "sendEmail", notes = "", response = EmailResponseDTO.class, tags={ "email-service", })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = EmailResponseDTO.class) })
@PostMapping(
value = "/email",
produces = { "application/json" },
consumes = { "multipart/mixed" }
)
default ResponseEntity<EmailResponseDTO> sendEmail(@ApiParam(value = "") @Valid @RequestPart(value = "sendTo", required = false) String sendTo,@ApiParam(value = "") @Valid @RequestPart(value = "sentFrom", required = false) String sentFrom,@ApiParam(value = "") @Valid @RequestPart(value = "subject", required = false) String subject,@ApiParam(value = "") @Valid @RequestPart(value = "content", required = false) String content,@ApiParam(value = "") @Valid @RequestPart(value = "file", required = false) MultipartFile file) {
return getDelegate().sendEmail(sendTo, sentFrom, subject, content, file);
}
}
这里是OpenAPI生成的API委托class(注意参数都是可选的):
public interface EmailServiceApiDelegate {
default ResponseEntity<EmailResponseDTO> sendEmail(Optional<String> sendTo,
Optional<String> sentFrom,
Optional<String> subject,
Optional<String> content,
MultipartFile file) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"errorMessage\" : \"errorMessage\", \"status\" : \"status\" }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
使用 allOf
将列出的所有架构合并为一个。 EmailRequestDTO
的属性和内联定义对象的属性是作为参数而不是作为 DTO 生成的。参见 https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/#allof
如果您不希望生成可选字符串作为委托中的参数,请删除 useOptional
配置。参见 https://openapi-generator.tech/docs/generators/spring/