Swagger OpenAPI Code Gen "oneOf" : How to generate correct class file?

Originally posted by zur on May 03, 2022

TLDR:

Swagger offers a feature named ‘oneOf’. The resulting java classes created do not seem to be correct.

Details:

I am creating the spring/java server side rest api code. And when I send a request. The request object is not parsed correctly. The following error is printed in the console.

JSON parse error: Could not resolve subtype of [simple type, class com.model.Issuer]: missing type id property 'type' (for POJO property 'issuer'); nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.Issuer]: missing type id property 'type' (for POJO property 'issuer')\n at [Source: (PushbackInputStream); line: 3, column: 15] (through reference chain: com.IssueCredentialRequest[\"credential\"]->com.Credential[\"issuer\"])

The reason seem to be that the generated class does not have subtypes:

package com.sphereon.vdp.vc.service.model;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
})
public interface OneOfIssuer {

}

There is another class which is generated correctly

package com.sphereon.vdp.vc.service.model;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = VerifyPresentationRequest.class, name = "VerifyPresentationRequest"),
@JsonSubTypes.Type(value = ProoflessVerifyPresentationRequest.class, name = "ProoflessVerifyPresentationRequest")
})
public interface OneOfpresentationsVerifyBody {

}

Can someone point to what am I missing?

<plugin>
   <groupId>io.swagger.codegen.v3</groupId>
   <artifactId>swagger-codegen-maven-plugin</artifactId>
   <version>3.0.33</version>
   <dependencies>
      <dependency>
         <groupId>com.github.jknack</groupId>
         <artifactId>handlebars</artifactId>
         <version>4.3.0</version>
      </dependency>
   </dependencies>
   <executions>
      <execution>
         <id>vc-rest-api-issuer-source-generation</id>
         <goals>
            <goal>generate</goal>
         </goals>
         <phase>generate-sources</phase>
         <configuration>
            <inputSpec>${pom.basedir}/specifications/issuer.yml</inputSpec>
            <language>spring</language>
            <apiPackage>com.company.vdp.vc.service.api</apiPackage>
            <modelPackage>com.company.vdp.vc.service.model</modelPackage>
            <artifactVersion>${project.version}</artifactVersion>
            <generateModels>true</generateModels>
            <generateApis>true</generateApis>
            <generateModelDocumentation>true</generateModelDocumentation>
            <generateSupportingFiles>true</generateSupportingFiles>
            <verbose>${openapi-codegen-verbose}</verbose>
            <output>${project.basedir}/target/generated-sources/java/api</output>
            <ignoreFileOverride>${project.basedir}/target/generated-sources/java/api/.swagger-codegen-ignore</ignoreFileOverride>
            <configOptions>
               <delegatePattern>true</delegatePattern>
               <dateLibrary>java8</dateLibrary>
               <useTags>true</useTags>
            </configOptions>
         </configuration>
      </execution>
      <execution>
         <id>vc-rest-api-verifier-source-generation</id>
         <goals>
            <goal>generate</goal>
         </goals>
         <phase>generate-sources</phase>
         <configuration>
            <inputSpec>${pom.basedir}/specifications/verifier.yml</inputSpec>
            <language>spring</language>
            <apiPackage>com.company.vdp.vc.service.api</apiPackage>
            <modelPackage>com.company.vdp.vc.service.model</modelPackage>
            <artifactVersion>${project.version}</artifactVersion>
            <generateModels>true</generateModels>
            <generateApis>true</generateApis>
            <generateModelDocumentation>true</generateModelDocumentation>
            <generateSupportingFiles>true</generateSupportingFiles>
            <verbose>${openapi-codegen-verbose}</verbose>
            <output>${project.basedir}/target/generated-sources/java/api</output>
            <ignoreFileOverride>${project.basedir}/target/generated-sources/java/api/.swagger-codegen-ignore</ignoreFileOverride>
            <configOptions>
               <delegatePattern>true</delegatePattern>
               <dateLibrary>java8</dateLibrary>
               <useTags>true</useTags>
            </configOptions>
         </configuration>
      </execution>
   </executions>
</plugin>

Following is the spec file that I am using without editing.

Originally posted by zur on May 03, 2022

Thanks for the comment. The post was a question. Not a general article. I am not sure how your response helps me solve the question. Thanks anyway.

Originally posted by dsinghvi77 on June 17, 2022

Hey zur –

I have hit similar issues and couple of things you can try:

  1. Changing the generator and possibly using OpenAPI (I have heard the Native Generator: https://openapi-generator.tech/docs/generators/java works the best)

  2. My team has been working on a Swagger alternative that really focuses on codegen (as Swagger was initially built for docs) and we are calling it Fern. Check it out here.
    In Fern you can represent the issuer like this:

Issuer:   union:     stringIssuer: string    objectIssuer: ObjectIssuerObjectIssuer:   fields:     id: string

and it will codegen the classes you want. Demo video here. Apologies if this wasn’t the answer you are looking for but I have run into many issues with codegen in the Swagger ecosystem and using an alternative feels like the best solution.

Originally posted by zur on June 28, 2022

Thank you for the response. I will suggest evaluation of the framework. But it may not be adopted currently. Thank you for your help.