【发布时间】:2021-10-15 05:04:51
【问题描述】:
我有一个 Spring Boot 应用程序,它使用 springdoc-openapi 为我的控制器生成 Swagger API 文档。 JSON 请求/响应中使用的枚举之一具有与其 value/toString() 不同的 JSON 表示。这是使用 Jackson @JsonValue 注释实现的:
public enum Suit {
HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");
@JsonValue
private final String jsonValue;
Suit(String jsonValue) { this.jsonValue = jsonValue; }
}
但是,在列出枚举值时,生成的 Swagger API 文档使用枚举值(特别是 toString() 的值)而不是 JSON 表示(根据 @JsonValue):
{
"openapi": "3.0.1",
"info": { "title": "OpenAPI definition", "version": "v0" },
"servers": [
{ "url": "http://localhost:8080", "description": "Generated server url" }
],
"paths": { ... },
"components": {
"schemas": {
"PlayingCard": {
"type": "object",
"properties": {
"suit": {
"type": "string",
"enum": [ "Hearts", "Diamonds", "Clubs", "Spades" ]
},
"value": { "type": "integer", "format": "int32" }
}
}
}
}
}
springdoc-openapi 项目中有一个关闭的问题#1101 请求允许@JsonValue 影响枚举序列化。但是,该问题是 closed,因为没有提交任何 PR。
如何获取枚举列表以匹配 REST 端点接受/返回的实际 JSON 类型,而不是 toString() 值?
我解决这个问题的第一个想法是使用来自Swagger Core 的@Schema(allowableValues = {...}] 注释。但是,无论是由于错误还是设计,这都会添加到值列表中,而不是替换它:
@Schema(allowableValues = {"Hearts", "Diamonds", "Clubs", "Spades"})
public enum Suit {
HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");
// ...
}
"suit": {
"type": "string",
"enum": [
"HEARTS",
"DIAMONDS",
"CLUBS",
"SPADES",
"Hearts",
"Diamonds",
"Clubs",
"Spades"
]
}
可重现的示例
plugins {
id 'org.springframework.boot' version '2.5.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'io.swagger.core.v3:swagger-annotations:2.1.10'
implementation 'org.springdoc:springdoc-openapi-ui:1.5.10'
implementation 'org.springframework.boot:spring-boot-starter-web'
}
package com.example.springdoc;
import com.fasterxml.jackson.annotation.JsonValue;
public class PlayingCard {
private Suit suit;
private Integer value;
public Suit getSuit() { return suit; }
public void setSuit(Suit suit) { this.suit = suit; }
public Integer getValue() { return value; }
public void setValue(Integer value) { this.value = value; }
public enum Suit {
HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");
@JsonValue
private final String jsonValue;
Suit(String jsonValue) { this.jsonValue = jsonValue; }
}
}
package com.example.springdoc;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/playingCard")
public class PlayingCardController {
@PostMapping
public PlayingCard echo(@RequestBody PlayingCard card) {
return card;
}
}
招摇网址:http://localhost:8080/v3/api-docs
【问题讨论】:
-
有JsonProperty、JsonCreator 和覆盖
toString()的选项。你能检查一下这些是否有效吗? -
JsonProperty和(正如问题中提到的)toString()工作。JsonCreator没有这样的运气(尽管它从一个值创建一个枚举并且没有以声明方式指定一个映射,但我认为它真的没有任何合理的方式可以工作)。跨度> -
@aksappy 谢谢;我已将
JsonProperty建议扩展为答案。
标签: java jackson swagger springdoc springdoc-openapi-ui