Skip to content

[JAVA] Discriminator not used in JSON.java #10196

@gravelld

Description

@gravelld
Description

When I generate client libs for an OpenAPI 3.0.1 YAML, discriminator settings are ignored in the generated JSON deserialisation code.

This means when deserialising JSON we can't enforce polymorphism/composition.

Swagger-codegen version

3.0.19

Swagger declaration file content or url
openapi: 3.0.1
info:
  title: Inheritance
  description: A description
  contact:
    email: me@example.com
  version: 0.0.0
paths:
  /pets:
    patch:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
              discriminator:
                propertyName: petType
      responses:
        '200':
          description: Updated
components:
  schemas:
    Pet:
      type: object
      required:
        - petType
      properties:
        petType:
          type: string
      discriminator: 
        propertyName: petType
    Dog:     # "Dog" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Dog`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Dog`
          properties:
            bark:
              type: boolean
            breed:
              type: string
              enum: [Dingo, Husky, Retriever, Shepherd]
    Cat:     # "Cat" is a value for the pet_type property (the discriminator value)
      allOf: # Combines the main `Pet` schema with `Cat`-specific properties 
        - $ref: '#/components/schemas/Pet'
        - type: object
          # all other properties specific to a `Cat`
          properties:
            hunts:
              type: boolean
            age:
              type: integer

The command line:

$ java -jar swagger-codegen-cli.jar generate \
-i inheritance.yaml \
-l java \
-o java

Generates this in JSON:

GsonFireBuilder fireBuilder = new GsonFireBuilder()
  .registerTypeSelector(Pet.class, new TypeSelector<Pet>() {
    @Override
    public Class<? extends Pet> getClassForElement(JsonElement readElement) {
        Map<String, Class<? extends Pet>> classByDiscriminatorValue = new HashMap<>();
            classByDiscriminatorValue.put("Cat".toUpperCase(), Cat.class);
            classByDiscriminatorValue.put("Dog".toUpperCase(), Dog.class);
            classByDiscriminatorValue.put("Pet".toUpperCase(), Pet.class);
        return getClassByDiscriminator(
                    classByDiscriminatorValue,
                    getDiscriminatorValue(readElement, ""));
    }
  })

Note the empty "" where the discriminator value (petType) should be.

When I try to deserialize:

java.lang.IllegalArgumentException: missing discriminator field: <>
	at io.swagger.client.JSON.getDiscriminatorValue(JSON.java:124)
	at io.swagger.client.JSON.access$0(JSON.java:121)
	at io.swagger.client.JSON$1.getClassForElement(JSON.java:62)
	at io.gsonfire.gson.TypeSelectorTypeAdapterFactory$TypeSelectorTypeAdapter.read(TypeSelectorTypeAdapterFactory.java:65)
	at io.gsonfire.gson.NullableTypeAdapter.read(NullableTypeAdapter.java:36)
	at io.gsonfire.gson.HooksTypeAdapter.deserialize(HooksTypeAdapter.java:86)
	at io.gsonfire.gson.HooksTypeAdapter.read(HooksTypeAdapter.java:54)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
	at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:932)
	at com.google.gson.Gson.fromJson(Gson.java:870)

When I generate using OpenAPI Generator::4.3.0:

GsonFireBuilder fireBuilder = new GsonFireBuilder()
        .registerTypeSelector(Pet.class, new TypeSelector() {
            @Override
            public Class getClassForElement(JsonElement readElement) {
                Map classByDiscriminatorValue = new HashMap();
                classByDiscriminatorValue.put("Dog".toUpperCase(Locale.ROOT), Dog.class);
                classByDiscriminatorValue.put("Cat".toUpperCase(Locale.ROOT), Cat.class);
                classByDiscriminatorValue.put("Pet".toUpperCase(Locale.ROOT), Pet.class);
                return getClassByDiscriminator(classByDiscriminatorValue,
                        getDiscriminatorValue(readElement, "petType"));
            }
  })
;

(petType is populated here).

Command line used for generation

Using the Gradle plugin, config as above.

Steps to reproduce

gradle generateSwaggerCodeInheritance

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions