使用Quarkus同步OpenAPI和JSON-B配置



迄今为止的比赛

我正试图按照官方指南,使用RESTEasy和JSON-B来启动并运行REST服务。我还添加了对OpenAPI的支持,以便按照本指南测试服务。

这两个部分都独立工作,服务正确地返回硬编码的演示数据。Swagger UI显示可用的路由并允许调用它们。

然而,它并不像我喜欢的那样平滑…

四处玩耍,我创建了一个返回包含Instant的对象的路由。在进行调用时,我会用一个ISO 8601格式的字符串来表示该属性,正如我所期望的那样。

然而,属性的关联架构是

Instant:
type: object
properties:
nanos:
format: int32
type: integer
seconds:
format: int64
type: integer
epochSecond:
format: int64
type: integer
nano:
format: int32
type: integer

这与实际返回的内容不一致。我有点明白它是从哪里来的。显然,quarkus-smallrye-openapi在检查Instant时使用了与quarkus-resteasy-jsonb不同的设置。

对于后者,我已经发现可以使用自定义JsonbAdapter来处理格式。例如:

public class JsonbInstantTypeAdapter implements JsonbAdapter<Instant, OffsetDateTime> {
@Override
public OffsetDateTime adaptToJson(Instant obj) {
return OffsetDateTime.ofInstant(obj, ZoneId.systemDefault());
}
@Override
public Instant adaptFromJson(OffsetDateTime obj) {
return obj.toInstant();
}
}
public class TestTimestamps {
@JsonbTypeAdapter(JsonbInstantTypeAdapter.class)
public Instant getDueTime() {
return Instant.now();
}
}

这导致Instant在转换到系统的时区后被序列化,从而在调试时更容易读取。

我只能部分地弄清楚如何调整这个模式。像这样注释方法:

public class TestTimestamps {
@Schema(type = SchemaType.STRING, format = "date-time")
public Instant getDueTime() {
return Instant.now();
}
}

结果生成了一个合适的示例值,但生成的模式仍然知道这是一个瞬间,所以它被生成为

dueTime:
allOf:
- $ref: '#/components/schemas/Instant'
- format: date-time
type: string

理想情况下,无论如何,我都不想单独注释每个方法。

问题

有没有办法配置项目范围内的为给定类型使用特定适配器?有没有一种方法可以确保生成的OpenAPI模式实际上代表的是经过调整的类型,而不是原始类型?

MicroProfile规范允许您覆盖特定类的模式

将其添加到Quarkusapplication.properties将覆盖日期模式

mp.openapi.schema.java.util.Date = { 
"name": "EpochMillis" 
"type": "number", 
"format": "int64", 
"description": "Milliseconds since January 1, 1970, 00:00:00 GMT" 
}

这将适用于您的Instant问题。看见https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#core-配置

Instant的一个短期解决方案是使用@Schema注释的implementation属性。当给出implementation时,smallrye-openapi中的注释扫描程序将忽略bean的方法/字段的类型(这将在示例输出中去掉$ref(。这种方法也适用于在OpenAPI中未使用其"自然"类型正确表示的任何其他Java类型。

public class TestTimestamps {
@Schema(implementation = String.class, format = "date-time")
public Instant getDueTime() {
return Instant.now();
}
}

最新更新