Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating definition for polymorphic types when only subclass is used #4181

Open
algattik opened this issue May 14, 2022 · 1 comment
Open

Comments

@algattik
Copy link

algattik commented May 14, 2022

We generate Swagger from JAX-RS/Jackson with polymorphic types, but do not reference the supertype in controllers.

This generates an incorrect OpenAPI type definition, where the discriminator field is missing.

package openapi.test;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;

import java.util.ArrayList;
import java.util.List;


@OpenAPIDefinition
@Path("/")
public class PolicyApiController {

    @POST
    public void createPolicy(Policy policy) {
    }

    // @POST
    // public void createRule(Rule policy) {
    // }

    @JsonTypeName("dataspaceconnector:permission")
    public static class Permission extends Rule {
    }

    public static class Policy {

        private final List<Permission> permissions = new ArrayList<>();
        private String target;

        public List<Permission> getPermissions() {
            return permissions;
        }

        public String getTarget() {
            return target;
        }
    }

    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            property = "type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = Permission.class, name = "dataspaceconnector:permission"),
    })
    public static abstract class Rule {

        private String target;

        public String getTarget() {
            return target;
        }

        public void setTarget(String target) {
            this.target = target;
        }
    }
}

Generated YAML definition:

components:
  schemas:
    Permission:
      type: object
      properties:
        target:
          type: string
    Policy:
      type: object
      properties:
        permissions:
          type: array
          items:
            $ref: '#/components/schemas/Permission'
        target:
          type: string

Uncommenting the createRule operation causes what appears to be the correct definition to be generated, as in #2340

components:
  schemas:
    Permission:
      type: object
      allOf:
      - $ref: '#/components/schemas/Rule'
    Policy:
      type: object
      properties:
        permissions:
          type: array
          items:
            $ref: '#/components/schemas/Permission'
        target:
          type: string
    Rule:
      required:
      - type
      type: object
      properties:
        target:
          type: string
        type:
          type: string
      discriminator:
        propertyName: type

Here's the build.gradle.kts file:

val jacksonVersion = "2.13.1"
val swagger = "2.2.0"
val rsApi = "3.1.0"

plugins {
    `java-library`
    id("io.swagger.core.v3.swagger-gradle-plugin") version "2.2.0"
}

repositories {
    mavenCentral()
}

dependencies {
    api("com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}")
    api("com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}")
    api("jakarta.ws.rs:jakarta.ws.rs-api:${rsApi}")
}


pluginManager.withPlugin("io.swagger.core.v3.swagger-gradle-plugin") {

    dependencies {
        implementation("io.swagger.core.v3:swagger-jaxrs2-jakarta:${swagger}")
        implementation("jakarta.ws.rs:jakarta.ws.rs-api:${rsApi}")
    }
    tasks.withType<io.swagger.v3.plugins.gradle.tasks.ResolveTask> {
        outputFileName = project.name
        outputFormat = io.swagger.v3.plugins.gradle.tasks.ResolveTask.Format.YAML
        prettyPrint = true
        classpath = java.sourceSets["main"].runtimeClasspath
        buildClasspath = classpath
        resourcePackages = setOf("openapi.test")
        outputDir = file("${rootProject.projectDir.path}/resources/openapi/yaml")
    }
    configurations {
        all {
            exclude(group = "com.fasterxml.jackson.jaxrs", module = "jackson-jaxrs-json-provider")
        }
    }
}
@erikpetzold
Copy link

We also have this problem.

Here would be an executable example: https://github.com/erikpetzold/swagger-duplicate-schema-generation/blob/main/src/main/java/de/epet/demo/issue1/ignoredparent/SwaggerDemo.java (project contains examples for more issues).

I also found #2863 which says this is intended behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants