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

[REQ] Make sure enums are unique #9135

Open
Shohou opened this issue Mar 30, 2021 · 9 comments
Open

[REQ] Make sure enums are unique #9135

Shohou opened this issue Mar 30, 2021 · 9 comments

Comments

@Shohou
Copy link

Shohou commented Mar 30, 2021

Is your feature request related to a problem? Please describe.

I got a json with spec version 2 from the third party vendor. It contains enums in some places and some of them have duplications. Of course this is a bug in json and should be fixed by the vendor, but would be nice if the generator checked it and removed duplications before generating java enums

Describe the solution you'd like

Check and remove duplicates from enums before generating java enums. Print a warning about duplications found

Describe alternatives you've considered

Well, so far I wrote a gradle script which parses json and removes duplicates before running generator. It makes my gradle script big and ugly

gradle plugin configuration

openApiGenerate {
    generatorName = "java"
    inputSpec = "$buildDir/generated/json/my.json".toString()
    validateSpec = false
    outputDir = "$buildDir/generated/myclasses".toString()
    apiPackage = "foo"
    invokerPackage = "bar"
    modelPackage = "foobarbar"
    configOptions = [
            dateLibrary         : 'java8',
            java8               : 'true',
            library             : 'native',
            serializationLibrary: 'jackson',
            useRuntimeException : 'true',
            asyncNative         : 'true'
    ]
    globalProperties = [
            apiDocs  : 'false',
            modelDocs: 'false',
            apiTests: 'false',
            modelTests: 'false'
    ]

    sourceSets.main.java.srcDirs += "$buildDir/generated/myclasses/src/main/java"
}

gradle plugin version - id "org.openapi.generator" version "5.0.1"

@Shohou
Copy link
Author

Shohou commented Mar 30, 2021

and just found that values in enums in my source json are actually unique if you take the letter case into consideration. But in java they are upped and become non unique

@GideonLeGrange
Copy link

I've also encountered this. Here is a YAML snippet that results in this problem:

       type:
          type: string
          description: Type of deal price.
          example: recurring
          enum:
          - TRANSFER
          - SETUP
          - RECURRING
          - RENEWAL
          - OVERUSE
          - setup
          - recurring
          - renewal

That leads to this Java code:

  /**
   * Type of deal price.
   */
  @JsonAdapter(TypeEnum.Adapter.class)
  public enum TypeEnum {
    TRANSFER("TRANSFER"),
    
    SETUP("SETUP"),
    
    RECURRING("RECURRING"),
    
    RENEWAL("RENEWAL"),
    
    OVERUSE("OVERUSE"),
    
    SETUP("setup"),
    
    RECURRING("recurring"),
    
    RENEWAL("renewal");

    private String value;

    TypeEnum(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }

    public static TypeEnum fromValue(String value) {
      for (TypeEnum b : TypeEnum.values()) {
        if (b.value.equals(value)) {
          return b;
        }
      }
      throw new IllegalArgumentException("Unexpected value '" + value + "'");
    }

    public static class Adapter extends TypeAdapter<TypeEnum> {
      @Override
      public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) throws IOException {
        jsonWriter.value(enumeration.getValue());
      }

      @Override
      public TypeEnum read(final JsonReader jsonReader) throws IOException {
        String value =  jsonReader.nextString();
        return TypeEnum.fromValue(value);
      }
    }
  }

@oujesky
Copy link
Contributor

oujesky commented Mar 4, 2022

This can also happen for enum values containing special characters (either part of the value or completely), example:

timezone:
    type: string
    enum:
        - "Etc/GMT-1"
        - "Etc/GMT+1"

this will generate enum values with duplicate names:

ETC_GMT_1("Etc/GMT-1"),
ETC_GMT_1("Etc/GMT+1");

Similar is reported for C# generator under #11265

In case the enum value contains just non-ascii characters, this is even worse as it generates invalid Java code. For example:

test:
    type: string
    enum: 
        - " "
        - "ěščřžýáí"

will result in code that not only has duplicate enum constants but additionally won't compile:

_(" "),
_("ěščřžýáí");

There are similar issues reported for other languages and similar use cases: #7441, #11207, #7288, #5110, #535 (comment)

@jonnekleijer
Copy link

jonnekleijer commented Jun 29, 2022

I found a similar use case for typescript-angular and csharp-netcore client generators.
The usecase is similar to @oujesky with non-ascii characters:

UnitOfMeasurement:
  type: string,
  enum: 
    - "m",
    - "",
    - ""

Result in typescript-angular:

export enum UnitOfMeasurement {
    M = 'm',
    M = 'm²',
    M = 'm³'
};

Result in csharp-netcore:

namespace Aquasuite.Api.Clients.Model
{
    /// <summary>
    /// Defines a magnitude of a quantity, defined and adopted by convention or by law,   that is used as a standard for measurement of the same kind of quantity.
    /// </summary>
    /// <value>Defines a magnitude of a quantity, defined and adopted by convention or by law,   that is used as a standard for measurement of the same kind of quantity.</value>
    [JsonConverter(typeof(StringEnumConverter))]
    public enum UnitOfMeasurement
    {
        /// <summary>
        /// Enum M for value: m
        /// </summary>
        [EnumMember(Value = "m")]
        M = 1,

        /// <summary>
        /// Enum M for value: m²
        /// </summary>
        [EnumMember(Value = "m²")]
        M = 2,

        /// <summary>
        /// Enum M for value: m³
        /// </summary>
        [EnumMember(Value = "m³")]
        M = 3
    }
}

Preferably duplicated values are not removed, as described in the request, but a way to submit a mapping for certain characters (possibly with a default).

@jonnekleijer
Copy link

An idea that would solve this, is to be able to extend the initializeSpecialCharacterMapping() where a user can submit a list of extra mappings.

@nickjs
Copy link

nickjs commented Sep 14, 2022

Also hitting this with a typescript-axios enum generated from pytz:

export const SubmissionTimezoneEnum = {
    // ...
    Gmt: 'GMT',
    Gmt0: 'GMT+0',
    Gmt0: 'GMT-0',
    Gmt0: 'GMT0',
    // ...
}

Even with initializeSpecialCharacterMapping recommended above, but it looks like typescript-axios is already stripping out special character mappings, so we may already be down a path that makes this tough to fix globally...

@mhaagens
Copy link

@nickjs Did you find a workaround for the issue with timezones?
Experiencing the same issue.

@nickjs
Copy link

nickjs commented Nov 21, 2022

Not a good one: I have a script that modifies the swagger.json after it's generated and before it's fed to openapi-generator that just renames all the timezones to use P and M instead of + and -.

@jornhd
Copy link
Contributor

jornhd commented Jan 20, 2023

Came across the same problem for csharp-netcore. Left a comment for this at bug
#11265 (comment)

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

No branches or pull requests

7 participants