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

How to generate enums along with the int -> string mapping #1993

Closed
chucklu opened this issue Mar 4, 2019 · 41 comments
Closed

How to generate enums along with the int -> string mapping #1993

chucklu opened this issue Mar 4, 2019 · 41 comments

Comments

@chucklu
Copy link
Contributor

chucklu commented Mar 4, 2019

I would like to show the enum with the int value and string.
I find a solution here, but it needs another library Swashbuckle.Core
https://stackoverflow.com/questions/36452468/swagger-ui-web-api-documentation-present-enums-as-strings

When I check the test code in source, I find https://github.com/RSuter/NSwag/blob/master/src/NSwag.SwaggerGeneration.WebApi.Tests/App_Start/SwaggerConfig.cs
What does it mean?Can I use NSwag and Swashbuckle at the same time?

Currently I am using NSwag with Owin,and the configuration is not GlobalConfiguration.Configuration. And I tried with the solution from stackoverflow, but it did not work.

@RicoSuter
Copy link
Owner

Swashbuckle is another swagger library and you should only use one to generate a spec... to enable string enums, set add a new serializer settings object in SerializerSettings with a global StringEnumConverter

@chucklu
Copy link
Contributor Author

chucklu commented Mar 5, 2019

Sorry, I don't understand.
What did you mean by a global StringEnumConverter?

I have already tried https://github.com/RSuter/NJsonSchema/wiki/JsonSchemaGenerator#integer-vs-string-enumerations
But it can only show integer value or string enum.

What I want is the integer with string enum. The following picture is from https://stackoverflow.com/questions/36452468/swagger-ui-web-api-documentation-present-enums-as-strings I mentioned before.
image

@chucklu
Copy link
Contributor Author

chucklu commented Mar 7, 2019

@RSuter Could you explain about the global StringEnumConverter you mentioned before?

@RicoSuter
Copy link
Owner

See #1234 (comment) (same problem?)

@chucklu
Copy link
Contributor Author

chucklu commented Mar 8, 2019

@RSuter I don't think so.
And that issue make me confused, why that guy ask question about Swashbuckle?
I did not want to use Swashbuckle, and you have told me

Swashbuckle is another swagger library and you should only use one to generate a spec



My problem is how to generate the enum with int value and string mapping by NSwag.
Previously, you are talking about

to enable string enums, set add a new serializer settings object in SerializerSettings with a global StringEnumConverter

However, I can not understand it. a new serializer settings object with a global StringEnumConverter
Could you give me a piece of code about it?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 13, 2019

Hi @RSuter ,
Any update?

@RicoSuter
Copy link
Owner

RicoSuter commented Mar 13, 2019

int value and string mapping by NSwag

Nswag will generate this by default (the x-enumNames property) but it is a custom property and only understood by the nswag client gens - you cannot express this with vanilla swagger/openapi

@chucklu
Copy link
Contributor Author

chucklu commented Mar 14, 2019

@RSuter I am using the NSwag according this document https://github.com/RSuter/NSwag/wiki/OWIN-Middleware

app.UseSwaggerUi3(configure): Registers the Swagger generator and Swagger UI v3.x on the given routes

Is this nswag client? If it's not ,then what is it?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 18, 2019

@RSuter Sorry to disturb you again, could you explain the question above?

@RicoSuter
Copy link
Owner

UseSwaggerUi3 only serves the Swagger UI, UseSwagger registers the swagger generator and then there are client generators which are usually used via NSwagStudio or CLI...

@chucklu
Copy link
Contributor Author

chucklu commented Mar 19, 2019

@RSuter As you mentioned before,

Nswag will generate this by default (the x-enumNames property) but it is a custom property and only understood by the nswag client gens - you cannot express this with vanilla swagger/openapi\

Then which method I supposed to use to make use of the nswag client gens?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

Hi @RicoSuter ,
Any update?

@RicoSuter
Copy link
Owner

What I want is the integer with string enum

If I understand correctly, the only thing you want is to have this description with the int/string mappings in the Swagger UI?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

Not sure, I did not see how the default UI works. Currently, I am using UseSwaggerUi3.
You can just told me how to make the enum show as expected.

@RicoSuter
Copy link
Owner

So you just want to see tjis in the web ui?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

What did you mean by tjis? Sorry for my poor English.

@RicoSuter
Copy link
Owner

tjis = this

Sorry, i do not understand your problem

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

the only thing you want is to have this description with the int/string mappings in the Swagger UI?

Yes, I want to see enum with int/string in Swagger UI

@RicoSuter
Copy link
Owner

So you only want that this description field in the ui is shown with the mappings?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

yes, exactly

@RicoSuter
Copy link
Owner

Ok 🙂

This feature is not availble yet, but it would be quite simple to implement. The idea is to put this behind a setting, eg GenerateEnumMappingDescription Which only applies for int enums and which will generate this description. Does this sound good?

Another better solution is to add support for x-enumNames to the Swagger UI project so that the ui just shows the names in the dropdown. Would this be a better solution for you?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

Thanks for your suggestion, I will try to figure it out.

@RicoSuter
Copy link
Owner

I can implement that... what do you think about my suggestions?

@chucklu
Copy link
Contributor Author

chucklu commented Mar 27, 2019

support for x-enumNames to the Swagger UI project so that the ui just shows the names in the dropdown

I agree with you, this solution might be better

@RicoSuter
Copy link
Owner

Ok, as soon as i’m on a pc i’ll create issues in the swagger ui and redoc projects and add the new setting to njsonschema/nswag.

@RicoSuter
Copy link
Owner

Created new issues in Swagger UI and ReDoc (was already there).

RicoSuter added a commit to RicoSuter/NJsonSchema that referenced this issue Mar 29, 2019
@RicoSuter
Copy link
Owner

RicoSuter commented Mar 29, 2019

Added GenerateEnumMappingDescription in NJS, needs to be added as CLI/UI setting in NSwag

@RicoSuter
Copy link
Owner

@ryan4664
Copy link

I am also looking to do something similar to this and I haven't been able to find any solutions. I'm working on an app that consumes an API. I've added generated nswag interfaces from our API and it's working great but I am having an issue with enums. The app currently uses them as integers and I'm unable to convert them all to strings as it would be a massive refactoring effort.

I have an enum in my API that looks like:

public enum NotificationType {   
        Unknown = 0,
        InAppMessage = 1,
        WinnerNotification = 2,
        PointsWinnerNotification = 3,
        ConsecutiveDays = 4,       
}

And I've only been able to generate

export enum NotificationType {
    _0 = 0,
    _1 = 1,
    _2 = 2,
    _3 = 3,
    _5 = 4,
}

or

export enum NotificationType {
        Unknown = "Unknown",
        InAppMessage = "InAppMessage",
        WinnerNotification = "WinnerNotification",
        PointsWinnerNotification = "PointsWinnerNotification",
        ConsecutiveDays = "ConsecutiveDays",
}

But I need a hybrid of the two such as

export enum NotificationType {
        Unknown = 0,
        InAppMessage = 1,
        WinnerNotification = 2,
        PointsWinnerNotification = 3,
        ConsecutiveDays = 4,
}

Is anyone able to point me in the right direction for this?

@bbarry
Copy link

bbarry commented Aug 25, 2020

I don't actually use NSwag for typescript generation but rather ng-openapi-gen: https://www.npmjs.com/package/ng-openapi-gen

That generator utilizes the x-enumNames member of the spec to generate:

export enum NotificationType {
        Unknown = 0,
        InAppMessage = 1,
        WinnerNotification = 2,
        PointsWinnerNotification = 3,
        ConsecutiveDays = 4,
}

I'm considering forking it to modify the enum template to generate in our project's style though:

import { Opaque } from 'ts-essentials';

export const SigningMethod = {
  Paper: 'paper' as Opaque<'paper', 'SigningMethod'>,
  Electronic: 'electronic' as Opaque<'electronic', 'SigningMethod'>,
  Transcribed: 'transcribed' as Opaque<'transcribed', 'SigningMethod'>,
} as const;

export type SigningMethod = typeof SigningMethod[keyof typeof SigningMethod];

The arch is easy to understand, it loads the spec and then runs a bunch of handlebars templates over the various components: https://github.com/cyclosproject/ng-openapi-gen

@mmaterowski
Copy link

mmaterowski commented Sep 22, 2020

@ryan4664 I'm using nSwag to generate specification and then open-api to generate TS client. For my case I needed to add x-enum-varnames data extension to specification, so client can be generated properly https://openapi-generator.tech/docs/templating/#enum

In order to do that I had to implement custom operation processor public class NSwagProcessor : IOperationProcessor and then implement Process method:

        JsonSchema schema = JsonSchema.FromType<YourType>();
        if (schema.ExtensionData == null)
        {
            schema.ExtensionData = new Dictionary<string, object>();
        }

        string[] enumerationNames = new string[schema.EnumerationNames.Count];
        schema.EnumerationNames.CopyTo(enumerationNames, 0);
        schema.ExtensionData.Add("x-enum-varnames", enumerationNames);

        if (context.Settings.TypeMappers.Any(t => t.MappedType == typeof(YourType)) == false)
        {
            context.Settings.TypeMappers.Add(new ObjectTypeMapper(typeof(YourType), schema));
        }

        return true;

in AddOpenApiDocument configuration method

settings.OpearationProcessors.Add(new NSwagProcessor());

This should do the trick for openapi-gen, but I can't be sure if it's the right solution for other generators. Tweaking other nSwag options and adding StringEnum serializer didn't work for me.

@kennydust
Copy link

is there a formal solution to this? we'd like to see the option for enums to be converted to string values ->

export enum NotificationTypeCurrent {
_0 = 0,
_1 = 1,
_2 = 2,
_3 = 3,
_5 = 4,
}

export enum NotificationTypeDesired {
EnumString1,
EnumString2,
EnumString3,
EnumString4,
}

@ericsampson
Copy link
Contributor

@RicoSuter it looks like someone submitted a PR to add this to swagger-ui, but the maintainers rejected putting it in the core project.
So instead the author created a swagger UI plugin to add this feature:
https://github.com/sapphi-red/swagger-ui-plugin-enum-names

Maybe this could be pulled into nswag?

Have you considered pulling in a new version of swagger-UI ? The latest couple patch versions have a fix for an annoying issue that we are running into.

@RicoSuter
Copy link
Owner

Just updated Swagger UI:
2682b04

@RicoSuter
Copy link
Owner

Maybe this could be pulled into nswag?

Can you add a PR to add this? Mainly to see how this would work...

@ramax495
Copy link

ramax495 commented Aug 30, 2022

With NSwag and System.Text.Json for me works:

services.AddControllersWithViews()
       .AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())) 

and

services.AddOpenApiDocument(configure =>
{
       ...
       configure.GenerateEnumMappingDescription = true;  
});

It accepts int-s and strings, generates enums in open-api and .ts client with names and show enums with names in SwaggerUI

export enum PaymentDirection {
    Input = "Input",
    Output = "Output",
}

@jenseralmeida
Copy link

Hi,

It does not work for me using newtonsoft, and only, or the numbers (without adding StringEnumConverter), or the enum names show up (when adding StringEnumConverter), on the UI.

@ramax495
Copy link

ramax495 commented Sep 2, 2022

It does not work for me using newtonsoft

Yes, it's solution with System.Text.Json

@jenseralmeida
Copy link

@ramax495, thanks for taking your time to answer it. Is there any plan to support the Newtonsoft library for this?

@harindaka
Copy link

harindaka commented Dec 5, 2023

@RicoSuter @ramax495 I get the following compilation error when trying to set options.GenerateEnumMappingDescription = true; in the configure lambda passed to the AddOpenApiDocument method (as mentioned above). Was the GenerateEnumMappingDescription property removed after this conversation? I'm using v14 of NSwag.AspNetCore

'AspNetCoreOpenApiDocumentGeneratorSettings' does not contain a definition for 'GenerateEnumMappingDescription' and no accessible extension method 'GenerateEnumMappingDescription' accepting a first argument of type 'AspNetCoreOpenApiDocumentGeneratorSettings' could be found (are you missing a using directive or an assembly reference?)

@ramax495
Copy link

ramax495 commented Dec 5, 2023

@harindaka look at the sources:

public JsonSchemaGeneratorSettings SchemaSettings { get; set; } = new SystemTextJsonSchemaGeneratorSettings

Property SchemaSettings was added. So try:

services.AddOpenApiDocument(configure =>
{
       ...
       configure.SchemaSettings.GenerateEnumMappingDescription = true;  
});

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

10 participants