英文:
springdoc-openapi spec generation for inheritance witth generics
问题
以下是您要翻译的内容:
我有一个Spring Boot(Kotlin)项目,我使用springdoc-openapi生成OpenApi 3规范。我的数据模型如下所示:
open class Animal
data class Cat(val catName: String) : Animal()
data class Dog(val dogName: String) : Animal()
open class Food<T : Animal>
class CatFood : Food<Cat>()
class DogFood : Food<Dog>()
以及一个简单的控制器如下:
@GetMapping("/test")
fun test(): Food<out Animal> = DogFood()
生成的YAML如下:
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8085
paths:
/test:
get:
tags:
- test-controller
operationId: test
responses:
"200":
description: default response
content:
'*/*':
schema:
$ref: '#/components/schemas/FoodAnimal'
components:
schemas:
FoodAnimal:
type: object
问题在于我的控制器可以返回DogFood
或CatFood
,并且这在返回类型中指定。我希望生成的模式如下:
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8085
paths:
/test:
get:
tags:
- test-controller
operationId: test
responses:
"200":
description: default response
content:
'*/*':
schema:
oneOf:
- $ref: '#/components/schemas/FoodAnimal'
- $ref: '#/components/schemas/DogFood'
- $ref: '#/components/schemas/CatFood'
components:
schemas:
FoodAnimal:
type: object
CatFood:
allOf:
- $ref: '#/components/schemas/FoodAnimal'
type: object
DogFood:
allOf:
- $ref: '#/components/schemas/FoodAnimal'
type: object
有没有办法实现这一点?
英文:
I have a Spring Boot (kotlin) project for which I use springdoc-openapi to generate OpenApi 3 spec. My data model looks like so:
open class Animal
data class Cat(val catName: String) : Animal()
data class Dog(val dogName: String) : Animal()
open class Food<T : Animal>
class CatFood : Food<Cat>()
class DogFood : Food<Dog>()
and a simple controller like so:
@GetMapping("/test")
fun test(): Food<out Animal> = DogFood()
for which the generated yaml is:
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8085
paths:
/test:
get:
tags:
- test-controller
operationId: test
responses:
"200":
description: default response
content:
'*/*':
schema:
$ref: '#/components/schemas/FoodAnimal'
components:
schemas:
FoodAnimal:
type: object
The problem here is that my controller can return either DogFood
or CatFood
, and that is specified in the return type. The schema I would expect to be generated is:
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8085
paths:
/test:
get:
tags:
- test-controller
operationId: test
responses:
"200":
description: default response
content:
'*/*':
schema:
oneOf:
- $ref: '#/components/schemas/FoodAnimal'
- $ref: '#/components/schemas/DogFood'
- $ref: '#/components/schemas/CatFood'
components:
schemas:
FoodAnimal:
type: object
CatFood:
allOf:
- $ref: '#/components/schemas/FoodAnimal'
type: object
DogFood:
allOf:
- $ref: '#/components/schemas/FoodAnimal'
type: object
Is there some way to achieve this?
答案1
得分: 13
对于继承,您只需要在父类上添加@Schema注释:
@Schema(
type = "object",
title = "Food",
subTypes = [CatFood::class, DogFood::class]
)
open class Food<T : Animal>
class CatFood : Food<Cat>()
class DogFood : Food<Dog>()
如果您需要使用oneOf获取响应,您将需要添加@Response:
@GetMapping("/test")
@ApiResponse(content = [Content(mediaType = "*/*", schema = Schema(oneOf = [Food::class, CatFood::class, DogFood::class]))])
fun test(): Food<out Animal> = DogFood()
英文:
For inheritance, you just need to add @Schema annotation, on your parent class:
@Schema(
type = "object",
title = "Food",
subTypes = [CatFood::class, DogFood::class]
)
open class Food<T : Animal>
class CatFood : Food<Cat>()
class DogFood : Food<Dog>()
If you need a reponse using oneOf, you will have to add @Response:
@GetMapping("/test")
@ApiResponse(content = [Content(mediaType = "*/*", schema = Schema(oneOf = [Food::class, CatFood::class,DogFood::class]))])
fun test(): Food<out Animal> = DogFood()
答案2
得分: 2
我在使用OpenApi时在嵌套属性的继承方面遇到了问题。
我使用了JsonSubtype注解和泛型作为一种解决方法。
data class AnimalResponse<FoodResponse>(
val id: UUID,
val eats: FoodResponse
)
@JsonSubTypes(value = [
JsonSubTypes.Type(
value = CatFoodResponse::class,
name = "CAT_FOOD"
), JsonSubTypes.Type(
value = DogFoodResponse::class,
name = "DOG_FOOD"
)])
interface FoodResponse
这将在AnimalResponse模式中显示所有类型的FoodResponses。
英文:
I had problems using OpenApi with inheritance for nested properties.
I used JsonSubtype annotations and generics as a workaround.
data class AnimalResponse<FoodResponse>(
val id: UUID,
val eats: FoodResponse
)
@JsonSubTypes(value = [
JsonSubTypes.Type(
value = CatFoodResponse::class,
name = "CAT_FOOD"
), JsonSubTypes.Type(
value = DogFoodResponse::class,
name = "DOG_FOOD"
)])
interface FoodResponse
This will show all types of FoodResponses in AnimalResponse Schema.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论