openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG][C#] Not possible to generate nullable enum in an API model

Open DavidJeppesen-Seges opened this issue 4 years ago • 6 comments

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

I am implementing a REST API for an international standard on dairy data. The standard is expressed in JSON Schema and we use the Open API Generator to generate the model. Unfortunately - no matter what I do, I can't get the generator to generate a nullable enum on the model. I have tried adding the "nullable": true property, adding null to the list of enum values, changed the type on the property to an array with null included as a type and finally I tried changing the reference to the type on the parent to be "oneOf" and adding null. Nothing works. According to other definitions and bugs I've seen, it should be enough that the enum is not required in the specs to make it nullable. Under the assumption that it should be possible to generate a nullable enum, I would like to know how it is done and if it is not possible, then I think it is a bug.

openapi-generator version

5.1.0

OpenAPI declaration file content or url

Root JSON Schema file

Generation Details

PowerShell command: npx openapi-generator-cli generate -i exampleUrlScheme.json -g aspnetcore -o c:\temp\generated

Steps to reproduce

Clone the above GIT repo, navigate to the folder where the exampleUrlScheme.json file resides and run the above command. Try also the changes I mentioned in the description on any enum type. I expect a nullable enum on enum types that are not required or at least when the type in any of the above mentioned ways is defined as nullable.

Related issues/PRs

I found a couple of open issues that might be related to this bug: #4816 #9022

Suggest a fix

Sorry - my Java is very rusty!

DavidJeppesen-Seges avatar Apr 06 '21 13:04 DavidJeppesen-Seges

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

auto-labeler[bot] avatar Apr 06 '21 13:04 auto-labeler[bot]

It's not possible to have a nullable in enum is C#. Rather than create a new issue, I am recording my observations here since it's closely related.

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [ ] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [x] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

The null-coalescing operator "??" can't be used on an enum. Hence, the following line in the generated code will have a compilation error:

this.ActualInstance = actualInstance ?? throw new ArgumentException("Invalid instance found. Must not be null.");

Actual error messages are:

Error	CS0019	Operator '??' cannot be applied to operands of type 'StatusAnyOf' and '<throw expression>'
Error	CS0019	Operator '??' cannot be applied to operands of type 'NullValue' and '<throw expression>'
openapi-generator version

Version used is 6.2.1. Did not test against the latest commit on the master branch.

OpenAPI declaration file content or url
openapi: 3.0.0
info:
  version: '1.0.0'
  title: 'Enum with null'
paths: {}
components:
  schemas:
    Entity:
      type: object
      properties:
        status:
          $ref: '#/components/schemas/Status'
    Status:
      anyOf:
        - type: string
          enum:
            - ACTIVE
            - PASSIVE
        - $ref: '#/components/schemas/NullValue'
        - type: string
    NullValue:
      enum:
        - null
Generation Details
java -jar C:\openapi-generator-cli.jar generate  -i C:\EnumNull.yaml -g csharp-netcore -o C:\EnumNull --additional-properties=targetFramework=net6.0 --additional-properties=packageName=Com.Example --skip-validate-spec
Steps to reproduce

Just run the command above and compile the generated model file. We will see the error.

Related issues/PRs

None

Suggest a fix

None

arvindpdmn avatar Jan 18 '23 13:01 arvindpdmn

@arvindpdmn

If I understand you correctly, you're saying that it is not possible to have a nullable enum in C#?

Well - it is... https://dotnetfiddle.net/NpVKdf

DavidJeppesen-Seges avatar Jan 18 '23 14:01 DavidJeppesen-Seges

@DavidJeppesen-Seges I am no expert in C#. I read that "An enum value cannot be null. It is a value type like an int." at https://www.dotnetperls.com/enum Your code sample makes sense. What I mean is that the code generator is using "??" operator on an enum. This is not allowed. Probably it should convert it to a string and then use the "??" operator, the way you have shown in your code.

arvindpdmn avatar Jan 18 '23 14:01 arvindpdmn

I've filed #14898 to workaround the issue using the openapi-normalizer.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g csharp-netcore -i /tmp/a.yaml -o /tmp/c2 --openapi-normalizer SIMPLIFY_ONEOF_ANYOF=true,SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING=true

wing328 avatar Mar 08 '23 11:03 wing328

Workaround no longer works now. Command line:

npx @openapitools/openapi-generator-cli generate -i NSwagFile.json -g csharp --skip-validate-spec --openapi-normalizer SIMPLIFY_ONEOF_ANYOF=true,SIMPLIFY_ANYOF_STRING_AND_ENUM_STRING=true

Getting tons of errors like Error CS0019 : Operator '??' cannot be applied to operands of type 'MyEnum' and '<throw expression>'

The only "workaround" is manually going through every case this error occurs and making the parameter nullable. i.e.: public MyClass(MyEnum actualInstance) -> public MyClass(MyEnum? actualInstance).

MaxwellDAssistek avatar Apr 30 '24 18:04 MaxwellDAssistek