简体   繁体   中英

Deserializing with Jackson (fail on unknown properties) does not ignore discriminator property (DTO's created with SwaggerCodegen)

EDIT:

I found the problem: I have to find a way to make swagger Codegen remove the "visible = true" part when it generates the java class. If i remove that manually it works. Problem is that the classes generate at compile-time and that modification will be overridden.

Stil need help!

Initial post:

I have the following:

  • a Reception entity class that has a List. Checkpoint is the base class, but it will only contain subclasses like Checkpoint1, Checkpoint2 etc.

  • a ReceptionCotroller that has an HTTP POST method mapped by "/receptions".

  • DTO classes for Reception and Checkpoints (Checkpoint base class, Checkpoint1, Checkpoint2 etc) generated with Swagger CodeGen openapi 3.0.2. using a yml file. The Checkpoint DTO has a discriminator field (in the yml file) named "dtype" so when deserializing the JSON into a Checkpoint, it knows what subclass it refers to.

The problem is when I add the property: spring.jackson.deserialization.fail-on-unknown-properties = true, it does not recognize the "dtype" property and it fails. I want the application to fail when it encounters unknown properties, but to ignore the "dtype".

I've tried to add a dtype field (beside the discriminator definition) in the Checkpoint DTO but then the JSON that returns as a response has 2 dtype fields (one with the discriminator value, and one with null).

Reception and Checkpoint in yml file:

Reception:
      description: description1
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: Id of the reception.
        checkpoints:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/Checkpoint1'
              - $ref: '#/components/schemas/Checkpoint2'
            discriminator:
              propertyName: dtype
            $ref: '#/components/schemas/Checkpoint'
          description: List of checkpoints attached to this reception.
Checkpoint:
      description: Checkpoint entity.
      type: object
      properties:
        checkpointId:
          type: string
          description: description1.
      required:
        - checkpointId
        - dtype
      discriminator:
        propertyName: dtype

Generated Checkpoint DTO class:

@ApiModel(description = "Checkpoint entity.")
@Validated
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "dtype", visible = true )
@JsonSubTypes({
  @JsonSubTypes.Type(value = Checkpoint1.class, name = "Checkpoint1"),
  @JsonSubTypes.Type(value = Checkpoint2.class, name = "Checkpoint2")
})
public class Checkpoint   {
  @JsonProperty("dtype")
  private String dtype = null;

  @JsonProperty("checkpointId")
  private String checkpointId = null;

(.....)

Json sent as request body:

{
    "id": 123,
    "checkpoints": [
        {
            "dtype": "Checkpoint1",
            "checkpointId": "Checkpoint1"
                }
    }

It says that it does not recognize dtype field. I want it to create the appropriate Checkpoint object, but ignore that the Checkpoint DTO does not actually contain a dtype field in the generated class. I DO NOT want it to ignore OTHER unknown properties. For example: if i add another "fooBar" field in the JSON, I want it to fail.

Hope the information provided is ok to understand what my problem is. If not, I can give further information.

Many thanks in advance!! PS: Please ignore eventual syntax errors or typos, the code works and copiles correctly, but i don't know how to ignore ONLY the discriminator (dtype) property.

There are two ways you could get this done.
First :
If you are allowed to change the auto generated java code, you can add the annotation @JsonIgnoreProperties(value = ["dtype"]) to all the classes that have discriminator fields like below.

@JsonIgnoreProperties(value = ["dtype"])
public class Checkpoint   {
//your properties here
}

An example implementation : Use of JsonIgnoreProperties specific property deserialize properties exists only in JSON The question has a sample implementation

Second:
If you are not allowed to edit the autogenerated java code, you can use Jackson Mixins to ignore specific unwanted fields .

@JsonIgnoreProperties(value = ["dtype"])
public abstract class CheckpointMixin {}

and in your object mapper register this mixin for the target class like below :

mapper.addMixIn(Checkpoint::class.java, CheckpointMixin::class.java)

I tried it out in kotlin and it worked as expected. Please ignore any syntactical inaccuraces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM