5

我在组件模式中使用 OpenAPI 3.0 继承,并且我有由 openapi-generator (使用 Jackson)生成的(Java)类。

为什么鉴别器属性在生成的 JSON 中被序列化两次?

这是一个 JHipster API-First 项目,它应该使用 openapi-generator 来生成 Java 模型(带有 Jackson 注释的 POJO)和 API 控制器(带有 Spring 的 @Api 注释的接口)。

通过遵循 OpenAPI 3.x 文档/示例,似乎使用 as 的属性discriminator也必须在properties模式列表中指定。

这样,生成的 Java 类似乎与 Jackson 使用注释的多态类型处理指南不同(此处),其中用作鉴别器的属性不得出现在类中。相反,生成的代码还包含此属性作为具有 getter/setter 的类属性。这会导致 JSON 输出包含该属性两次,如下所示。

我还尝试从 OpenAPIproperties列表中删除该属性,保留完整的discriminator部分;这样生成的代码符合杰克逊的指导方针,并且序列化工作得很好。另一方面,我在反序列化过程中遇到错误,因为在目标类中找不到(删除的)属性。

遵循 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",
        ...
}

我希望通过遵循 OpenAPI 3.x 指南,生成的类能够正确序列化/反序列化。

(边注)

在反序列化过程中,使用上述方法,您可能会收到以下错误:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type" (class it.blutec.bludesk.web.api.model.TicketMovedEvent), not marked as ignorable ...

要解决此问题,您需要配置 Jackson ObjectMapper 对象以忽略这种情况。

ObjectMapper om = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
4

4 回答 4

2

我自己也遇到了这个。在 OpenApi 属性列表中不包括鉴别器字段确实可以解决序列化时的双字段问题,同时在反序列化时导致 UnrecognizedPropertyException。经过反复试验,我发现可以通过在生成的代码中删除注释的"visible = true"属性(或将其设置为 false)来解决第二个问题。@JsonTypeInfo(如果您将构建过程设置为始终从开放 API 规范重新生成代码,那么当然,这不是真正的解决方案)。

于 2019-10-29T13:55:35.727 回答
1

我刚遇到同样的问题。问题在于@JsonTypeInfo生成的模型类上的注释。

它被生成为 -

@JsonTypeInfo(... include = JsonTypeInfo.As.PROPERTY ...)

这在模型中添加了一个额外的属性。

如果我在生成的代码中将其更改为 -

@JsonTypeInfo(... include = JsonTypeInfo.As.EXISTING_PROPERTY ...)

它使用模型中已经存在的属性,一切正常。

但是,当我重新生成代码时,这种更改当然会丢失。如果有人找到了永久解决方案,那就太好了。

于 2020-08-31T06:48:12.393 回答
1

我相信我在https://github.com/OpenAPITools/openapi-generator/pull/5120中解决了这个问题,它应该与 openapi-generator 4.3 版本一起发布。随意检查一下(由于那个 PR,oneOf 支持也应该得到很大改善)。

于 2020-01-29T13:04:23.983 回答
0

只想为 Soham 的回答中描述的问题添加解决方法。

如果您正在使用spring-boot-maven-plugin,您可以覆盖项目中的 mustache 模板以修复生成的代码。

在项目的根目录中添加一个名为openapi-generator-templates.

在 pom.xml 文件中,在插件的配置节点中添加这一行(不是 configOptions)

<templateDirectory>${project.basedir}/openapi-generator-templates</templateDirectory>

在该文件夹中,从 Github 上的openapi-generator 项目中复制 mustache 模板。

我正在使用 kotlin-spring 生成器,所以对我来说模板就在这里

编辑胡子文件替换JsonTypeInfo.As.PROPERTYJsonTypeInfo.As.EXISTING_PROPERTY

(作为旁注,在 kotlin-spring 生成器中要让继承工作,您还应该对dataClass.mustache模板使用类似的解决方法。有关此错误的更多信息here)。

于 2021-08-11T08:34:14.267 回答