为什么鉴别器属性被序列化两次?

nic*_*hoe 5 java jackson swagger swagger-codegen openapi-generator

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

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

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

通过遵循 OpenAPI 3.x 文档/示例,似乎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'
Run Code Online (Sandbox Code Playgroud)

生成的类:

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'
Run Code Online (Sandbox Code Playgroud)

JSON 包含两次属性:

{
        ...
    "type": "TicketMovedEvent",
    "type": null,
        ...
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

生成的没有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   {
   ...

   @JsonProperty("type")
   private String type;
Run Code Online (Sandbox Code Playgroud)

JSON 现在是正确的:

{
        ...
    "type": "TicketMovedEvent",
        ...
}
Run Code Online (Sandbox Code Playgroud)

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

(边注)

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

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

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

{
        ...
    "type": "TicketMovedEvent",
    "type": null,
        ...
}
Run Code Online (Sandbox Code Playgroud)

小智 2

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