为什么鉴别器属性被序列化两次? [英] Why discriminator property gets serialized twice?

查看:77
本文介绍了为什么鉴别器属性被序列化两次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using OpenAPI 3.0 inheritance in components schemas and I have the (Java) classes generated by openapi-generator (which uses Jackson).

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

Why the discriminator property gets serialized twice in the resulting JSON?

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

This is a JHipster API-First project, which should use openapi-generator for generating the Java model (POJOs with Jackson annotations) and API controllers (interfaces with Spring's @Api annotations).

通过遵循OpenAPI 3.x文档/示例,似乎还必须在架构的properties列表中指定用作discriminator的属性.

By following the OpenAPI 3.x documentation/examples, it seems that the property used as discriminator must also be specified in the properties list of the schema.

这样,生成的Java类似乎与带注释的多态类型处理的杰克逊准则(这里),其中用作区分符的属性不能出现在类中.相反,生成的代码还将此属性作为具有getter/setter的类属性包括在内.这将导致JSON输出两次包含该属性,如下所示.

This way, the generated Java class seems to differ from the Jackson guidelines for polymorphic type handling with annotations (here), where the property used as discriminator must not be present in the class. Instead, the generated code also includes this property as a class attribute with getter/setter. This causes the JSON output to include the property twice, as shown below.

我还尝试从OpenAPI properties列表中删除该属性,而保留discriminator部分的完整性.这样,生成的代码符合Jackson的准则,并且序列化工作正常.另一方面,在反序列化过程中出现错误,因为在目标类中找不到(已删除)属性.

I've also tried to remove the property from the OpenAPI properties list, leaving intact the discriminator part; this way the generated code corresponds to the Jackson's guidelines and the serialization works just fine. On the other hand, I get an error during the deserialization process because the (removed) property is not found in the target class.

遵循OpenAPI 3.x doc准则:

Following the OpenAPI 3.x doc guidelines:

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列表中删除discriminator属性:

Removing the discriminator property from properties list:

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属性的生成的类:

Generated class without type property:

@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现在是正确的:

The JSON now is correct:

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

我希望遵循OpenAPI 3.x准则,可以正确地对生成的类进行序列化/反序列化.

I would expect that, by following the OpenAPI 3.x guidelines, the generated class to be properly serialized/deserialized.

(旁注)

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

During deserialization, by using the aforementioned approach, you might get the following error:

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

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

To fix this, you need to configured the Jackson ObjectMapper object to ignore this kind of situations.

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

推荐答案

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

Just ran into this myself. Not including the discriminator field in the OpenApi properties list does indeed take care of the double-field problem upon serialization, while causing an UnrecognizedPropertyException upon deserialization. With some trial and error, I found that the 2nd problem can be solved by deleting the "visible = true" property (or setting it to false) of the @JsonTypeInfo annotation in the generated code. (If you have your build process setup to always re-generate code from the open API spec then, of course, this is not a real solution).

这篇关于为什么鉴别器属性被序列化两次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆