RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.78k stars 1.29k forks source link

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

Closed chucklu closed 5 years ago

chucklu commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

RicoSuter commented 5 years ago

See https://github.com/RSuter/NSwag/issues/1234#issuecomment-470519135 (same problem?)

chucklu commented 5 years ago

@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 commented 5 years ago

Hi @RSuter , Any update?

RicoSuter commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

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

RicoSuter commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

Hi @RicoSuter , Any update?

RicoSuter commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

chucklu commented 5 years ago

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

RicoSuter commented 5 years ago

tjis = this

Sorry, i do not understand your problem

chucklu commented 5 years ago

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 commented 5 years ago

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

chucklu commented 5 years ago

yes, exactly

RicoSuter commented 5 years ago

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 commented 5 years ago

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

RicoSuter commented 5 years ago

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

chucklu commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

RicoSuter commented 5 years ago

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

RicoSuter commented 5 years ago

Ref: https://github.com/mozilla-services/react-jsonschema-form/pull/1054

ryan4664 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

@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 commented 3 years ago

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 commented 3 years ago

@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 commented 3 years ago

Just updated Swagger UI: https://github.com/RicoSuter/NSwag/commit/2682b04d055996a78f18a107895352815348f1d8

RicoSuter commented 3 years ago

Maybe this could be pulled into nswag?

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

ramax495 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

It does not work for me using newtonsoft

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

jenseralmeida commented 2 years ago

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

harindaka commented 11 months ago

@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 commented 11 months ago

@harindaka look at the sources: https://github.com/RicoSuter/NSwag/blob/6858a7ecc8b461c469341093349166f7ff37ef4a/src/NSwag.Generation/OpenApiDocumentGeneratorSettings.cs#L30

Property SchemaSettings was added. So try:

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