Forum Discussion

sylvaman's avatar
sylvaman
Occasional Visitor
4 years ago

oneOf polymorphic Property

Hi,

I require a polymorphic property in my specification. 

To demonstrate the  requirement, I have modified the Pet example by adding a booking schema object that has a polymorphic pet property.

3.0.24 Java codegen runs without error and the generated code compiles. 

{
  "openapi": "3.0.2",
  "info": {
    "title": "Communication Model",
    "version": "141405445",
  },
  "paths": {
  },
  "components": {
    "schemas": {
      "booking": {
        "type": "object",
        "properties": {
          "pet": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Cat"
              },
              {
                "$ref": "#/components/schemas/Dog"
              }
            ],
            "discriminator": {
              "propertyName": "petType",
              "mapping": {
                "dog": "#/components/schemas/Dog",
                "cat": "#/components/schemas/Cat"
              }
            }
          },
          "foo" : {
            "type": "string"
          }
        }
      },
      "Pet": {
        "type": "object",
        "discriminator": {
          "propertyName": "petType"
        },
        "properties": {
          "name": {
            "type": "string"
          },
          "petType": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "petType"
        ]
      },
      "Cat": {
        "description": "A representation of a cat. Note that `Cat` will be used as the discriminator value.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Pet"
          },
          {
            "type": "object",
            "properties": {
              "huntingSkill": {
                "type": "string",
                "description": "The measured skill for hunting",
                "default": "lazy",
                "enum": [
                  "clueless",
                  "lazy",
                  "adventurous",
                  "aggressive"
                ]
              }
            },
            "required": [
              "huntingSkill"
            ]
          }
        ]
      },
      "Dog": {
        "description": "A representation of a dog. Note that `Dog` will be used as the discriminator value.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Pet"
          },
          {
            "type": "object",
            "properties": {
              "packSize": {
                "type": "integer",
                "format": "int32",
                "description": "the size of the pack the dog is from",
                "default": 0,
                "minimum": 0
              }
            },
            "required": [
              "packSize"
            ]
          }
        ]
      }
    }
  }
}

 However, I have an issue serializing and deserializing the Booking class with the pet polymorphic property.

 

The generated Booking class looks like this:

public class Booking   {
  @JsonProperty("pet")
  private OneOfbookingPet pet = null;

Where OneOfbookingPet is a marker interface.

public interface OneOfbookingPet {
}

The Pet super class has the Jackson annotations.

@JsonSubTypes({
        @JsonSubTypes.Type(value = Cat.class, name = "Cat"),
        @JsonSubTypes.Type(value = Dog.class, name = "Dog"),
})
public class Pet   {

Concrete Pet implementations extend and Pet and Implement OneOfbookingPet.

public class Dog extends Pet implements OneOfbookingPet {

 

Serializing a Booking object results in the JSON below:

{"pet":{"name":"Fido","packSize":4},"foo":"bar"}

However deserializing it back into a Booking object obviously fails. 

The type of the pet property in Booking is OneOfbookingPet which has no Jackson annotations, so no discriminator is added to the JSON.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `domain.OneOfbookingPet` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: (String)"{"pet":{"name":"Fido","packSize":4},"foo":"bar"}"; line: 1, column: 8] (through reference chain: domain.Booking["pet"])

Are polymorphic properties supported? What have I done wrong?

Any help appreciated.

Cheers,

Paul

No RepliesBe the first to reply