我在组件模式中使用OpenAPI 3.0继承,并且我有openapi-generator(使用Jackson)生成的(Java)类。
为什么discriminator属性在生成的JSON中被序列化两次?
这是一个JHipster API-First项目,应该使用openapi-generator来生成Java模型(带有Jackson注释的POJO)和API控制器(带有Spring的@Api注释的接口)。
通过遵循OpenAPI 3.x文档/示例,似乎还必须在模式的discriminator
列表中指定用作properties
的属性。
这样,生成的Java类似乎与带注释(here的多态类型处理的Jackson准则有所不同,在该准则中,用作鉴别符的属性必须不存在于类中。相反,生成的代码还将此属性作为具有getter / setter的类属性包括在内。这将导致JSON输出两次包含该属性,如下所示。
我还尝试了从OpenAPI properties
列表中删除该属性,而保留了discriminator
部分;这样,生成的代码符合Jackson的准则,并且序列化工作正常。另一方面,在反序列化过程中出现错误,因为在目标类中找不到(已删除)属性。
遵循OpenAPI 3.x文档准则:
TicketEvent:
type: object
description: A generic event
discriminator:
propertyName: type
required:
- id
- sequenceNumber
- timestamp
- type
properties:
id:
type: integer
format: int64
readOnly: true
sequenceNumber:
type: integer
readOnly: true
timestamp:
type: string
format: date-time
readOnly: true
type:
type: string
readOnly: true
TicketMovedEvent:
description: A ticket move event
allOf:
- $ref: '#/components/schemas/Event'
- type: object
required:
- source
- target
properties:
source:
$ref: '#/components/schemas/Queue'
target:
$ref: '#/components/schemas/Queue'
生成的类:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = TicketMovedEvent.class, name = "TicketMovedEvent")
})
public class TicketEvent {
...
@JsonProperty("type")
private String type;
JSON包含属性两次:
{
...
"type": "TicketMovedEvent",
"type": null,
...
}
从properties
列表中删除鉴别属性:
TicketEvent:
type: object
description: A generic event
discriminator:
propertyName: type
required:
- id
- sequenceNumber
- timestamp
properties:
id:
type: integer
format: int64
readOnly: true
sequenceNumber:
type: integer
readOnly: true
timestamp:
type: string
format: date-time
readOnly: true
不具有type
属性的生成的类:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = TicketMovedEvent.class, name = "TicketMovedEvent")
})
public class TicketEvent {
...
// now the "type" property is missing
})
JSON现在是正确的:
{
...
"type": "TicketMovedEvent",
...
}
但是在反序列化期间,出现以下错误:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type" (class it.blutec.bludesk.web.api.model.TicketMovedEvent), not marked as ignorable ...
我希望遵循OpenAPI 3.x准则,可以正确地对生成的类进行序列化/反序列化。
答案 0 :(得分:1)
我自己碰到了这个。实际上,在OpenApi属性列表中不包括discriminator字段确实可以解决序列化时的双字段问题,同时在反序列化时导致UnrecognizedPropertyException。
经过反复试验,我发现可以通过在生成的代码中删除"visible = true"
批注的@JsonTypeInfo
属性(或将其设置为false)来解决第二个问题。 (如果您有构建过程的设置,可以始终根据开放的API规范重新生成代码,那么,这当然不是真正的解决方案。)
答案 1 :(得分:1)
我相信我在https://github.com/OpenAPITools/openapi-generator/pull/5120中解决了该问题,该问题应该与openapi-generator 4.3版本一起发布。随时检查一下(由于该PR,oneOf支持也应大大改善)。
答案 2 :(得分:0)
我刚遇到同样的问题。问题出在生成的模型类上的@JsonTypeInfo
注释上。
其生成方式为-
@JsonTypeInfo(... include = JsonTypeInfo.As.PROPERTY ...)
这会在模型中添加一个额外的属性。
如果我在生成的代码中将其更改为-
@JsonTypeInfo(... include = JsonTypeInfo.As.EXISTING_PROPERTY ...)
它使用模型中已经存在的属性,并且一切正常。
但是,当我重新生成代码时,此更改当然会丢失。 如果有人找到了永久解决方案,那就太好了。
答案 3 :(得分:0)
只想为 Soham 的回答中描述的问题添加一个解决方法。
如果您使用 spring-boot-maven-plugin
,您可以覆盖项目中的 mustache 模板以修复生成的代码。
在项目的根目录中添加一个名为 openapi-generator-templates
的文件夹。
在 pom.xml 文件中,在插件的配置节点(NOT configOptions)中添加这一行
<templateDirectory>${project.basedir}/openapi-generator-templates</templateDirectory>
在文件夹内从 Github 上的 openapi-generator project 复制 mustache 模板。
我使用的是 kotlin-spring 生成器,所以对我来说模板是 here。
编辑小胡子文件,将 JsonTypeInfo.As.PROPERTY
替换为 JsonTypeInfo.As.EXISTING_PROPERTY
(作为旁注,要在 kotlin-spring 生成器中进行继承,您还应该对 dataClass.mustache
模板使用类似的解决方法。有关此错误 here 的更多信息)。