返回

歧视器属性的双重序列化之谜:深入解析解决方案

java

歧视器属性的双重序列化之谜

导言

在 OpenAPI 3.0 的组件模式中使用继承时,歧视器属性可能会意外地被序列化两次。了解问题的原因并找到解决方法至关重要。本文将深入探讨这个问题,并提供一个清晰的解决方案。

背景

在 JHipster API 优先项目中,使用 openapi-generator 来生成 Java 代码。根据 OpenAPI 3.x 规范,作为“歧视器”的属性也必须在模式的“属性”列表中指定。

问题

然而,生成的 Java 类没有遵循 Jackson 多态类型处理注解指南。生成的代码包含一个类属性,用于歧视器属性,带有 getter/setter。这导致 JSON 输出包含该属性两次。

原因

原因在于生成的代码不符合 Jackson 的指南,其中歧视器的属性不应存在于类中。相反,它将该属性作为类属性。

尝试的解决方案

尝试从 OpenAPI“属性”列表中删除歧视器属性,但反序列化过程失败,因为目标类中找不到(已删除的)属性。

解决方案

通过仔细检查 OpenAPI 3.x 文档,我们发现了一个解决方法。要防止歧视器属性的双重序列化,只需从 OpenAPI 的“属性”列表中删除该属性即可。这样,生成的 Java 类将符合 Jackson 的指南,并且序列化/反序列化将正常工作。

示例

为了说明这一点,考虑以下 OpenAPI 模式:

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'

生成的 Java 类将如下所示:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = TicketMovedEvent.class, name = "TicketMovedEvent")
})

public class TicketEvent   {
   ...

   // "type" 属性已从类中删除
})

JSON 输出将是正确的:

{
        ...
    "type": "TicketMovedEvent",
        ...
}

结论

遵循 OpenAPI 3.x 规范可以生成可以正确序列化/反序列化的类。通过从 OpenAPI 的“属性”列表中删除歧视器属性,我们可以防止歧视器属性的双重序列化并确保正确的数据处理。

常见问题解答

  1. 歧视器属性是什么?
    歧视器属性是一个用于区分继承类中子类型的属性。

  2. 为什么歧视器属性有时会序列化两次?
    在 Java 中,根据 Jackson 的指南,歧视器属性不应存在于类中。然而,openapi-generator 生成的代码包含一个歧视器属性的类属性,导致双重序列化。

  3. 如何解决歧视器属性的双重序列化问题?
    从 OpenAPI 的“属性”列表中删除歧视器属性。

  4. 如果我从“属性”列表中删除了歧视器属性,反序列化会发生什么?
    反序列化将失败,因为目标类中找不到(已删除的)属性。

  5. 在解决歧视器属性的双重序列化问题时,我应该注意哪些其他事项?
    确保生成的类符合 Jackson 多态类型处理注解指南,并配置 ObjectMapper 对象以忽略未知属性。