Nswag: [Suggestion] Consider adding support for snake_case

Created on 15 Feb 2017  路  16Comments  路  Source: RicoSuter/NSwag

I work with several services that use the snake_case naming convention for models. It would be nice if NSwag supported it out of the box.

Samples (CSharp / TypeScript):

  • Foo-bar => FooBar / fooBar
  • Foo_Bar => FooBar / fooBar
  • @Foo => Foo / foo
  • Foo-bar- => FooBar / fooBar
enhancement

All 16 comments

Do you need this in the Swagger generator or Code generators?

I'm generating .NET clients from swagger specifications. So, my immediate need is for code generation. But someone might be generating swagger specifications from services that will be consumed by platforms that favor snake_case.

+1

I would also like to have that for code generation of C# classes. I can also create a pull request for this if you like to. I had a look and would adjust the CSharpPropertyNameGenerator (convert underscore to dash and then call ConvertToUpperCamelCase) and add a new CSharpTypeNameGenerator (inherit from DefaultTypeNameGenerator and overwrite method Generate(JsonSchema4 schema, string typeNameHint).

My question is: Why would you do that? I mean why would you generate code which does not conform the C# style?

Can this be completely achieved by implementing an own PropertyNameGenerator?

No - it is exactly vice-versa :) From a definition "vouchers_create" you create a class with the name "Vouchers_create". And I (and I think also Paul) would like it to be "VouchersCreate". Your existing code just replaces dashes ("-") into camel case but leaves underscores untouched (meaning the NJsonSchema one).

ah then its fine :)

public class CSharpPropertyNameGenerator : IPropertyNameGenerator
{
    public virtual string Generate(JsonProperty property)
    {
        return ConversionUtilities.ConvertToUpperCamelCase(property.Name
            .Replace("@", "")
            .Replace(".", "-"), true)
            .Replace("-", "_");
    }
}

Should be:

/// <summary></summary>
    public virtual string Generate(JsonProperty property)
    {
        return ConversionUtilities.ConvertToUpperCamelCase(property.Name
            .Replace("@", "")
            .Replace(".", "-")
            .Replace("_", "-"), true)
            .Replace("-", "_");
    }

In NJsonSchema

The problem is: This is a major breaking change. If we do this, we should make it correct for all cases in one release. We cannot change this for each version...

We should define "all" possible inputs and the expected outputs in the issue text, write unit tests and implement that...

Related: https://github.com/NSwag/NSwag/issues/570

That is the place in code - I have it more like the following where I replace the underscore first. I did not test but the "ConvertToUpperCamelCase" should replace the dashes to camelCase.

            return ConversionUtilities.ConvertToUpperCamelCase(property.Name.Replace('_', '-')
                .Replace("@", "")
                .Replace(".", "-"), true);

But in general - the CodeGeneratorSettingsBase allows setting Type and Property naming generators. The other is about the enum but they seem to use the ConvertToUpperCamelCase logic as well in the DefaultEnumNameGenerator.

But I am not deep enough into the whole solution to know if that is every possible input.

We have these tree extension points:

    /// <summary>Gets or sets the property name generator.</summary>
    [JsonIgnore]
    public IPropertyNameGenerator PropertyNameGenerator { get; set; }

    /// <summary>Gets or sets the type name generator.</summary>
    [JsonIgnore]
    public ITypeNameGenerator TypeNameGenerator { get; set; } = new DefaultTypeNameGenerator();

    /// <summary>Gets or sets the enum name generator.</summary>
    [JsonIgnore]
    public IEnumNameGenerator EnumNameGenerator { get; set; } = new DefaultEnumNameGenerator();

Where TypeNameGenerator generates the class name in CSharp... I think we should add many more unit tests with the expected names for each generation implementation (CSharp and TypeScript)

For now, you can replace them with own implementations, but the default implementations should also work as good as possible with all possible inputs (i.e. strange chars, _, -, . etc)

Yes, the solution is name generators. But having them out of the box is easier for those using the T4 template generator.

For a quick and dirty solution you can adjust the NSwag.CodeGeneration.CSharp.SwaggerToCSharpGeneratorSettings and add some new generators:

                PropertyNameGenerator = new CustomCSharpPropertyNameGenerator(),
                TypeNameGenerator = new CustomCSharpTypeNameGenerator(),
                EnumNameGenerator = new CustomEnumNameGenerator(),

CustomCSharpPropertyNameGenerator:

    /// <summary>
    /// Custom property name generator to not have underscores in the name
    /// </summary>
    public class CustomCSharpPropertyNameGenerator : IPropertyNameGenerator
    {
        /// <summary>Generates the property name.</summary>
        /// <param name="property">The property.</param>
        /// <returns>The new name.</returns>
        public virtual string Generate(JsonProperty property)
        {
            return ConversionUtilities.ConvertToUpperCamelCase(property.Name.Replace('_', '-')
                .Replace("@", "")
                .Replace(".", "-"), true);
        }
    }

CustomCSharpTypeNameGenerator:

    /// <summary>
    /// Custom type name generator to not have underscores in the name
    /// </summary>
    public class CustomCSharpTypeNameGenerator : DefaultTypeNameGenerator
    {
        /// <inheritdoc />
        protected override string Generate(JsonSchema4 schema, string typeNameHint)
        {
            var lastSegment = typeNameHint?.Split('.').Last();
            return ConversionUtilities.ConvertToUpperCamelCase(lastSegment?.Replace('_', '-') ?? "Anonymous", true);
        }
    }

CustomEnumNameGenerator:

    /// <summary>
    /// Custom enum name generator to not have underscores in the name
    /// </summary>
    public class CustomEnumNameGenerator : IEnumNameGenerator
    {
        /// <inheritdoc />
        public string Generate(int index, string name, object value, JsonSchema4 schema)
        {
            return ConversionUtilities.ConvertToUpperCamelCase(name
                .Replace(":", "-").Replace('_', '-'), true)
                .Replace(".", "_");
        }
    }

At least for my use case that is now producing namings in normal C# style.

@RicoSuter When using NSwag.MSBuild, how should one implement a custom PropertyNameGenerator?

With NSwag.MSBuild you cannot do that at the moment (its not possible to load additional custom assemblies with a generator). Currently you鈥檇 need to implement your own cli based on the nswag packages.

I think this should be an option on the command line or in the UI, because I just ran into this myself trying to use this tool and quickly discovered that it's not producing the naming in the normal C# convention. For our REST code, we generally prefer attribute free programming so just want simple POCO classes without all the Newtonsoft.Json.JsonProperty() attributes and set up the JSON converters to match whatever REST service we are communicating with. But that won't work unless it can generate correct C# POCO classes, so it would be nice for this to be an option.

Pull request is completed for this, along with the UI options. I also added an option to disable the Async suffix which IMHO is pointless if you are only going to have an Async API.

https://github.com/RicoSuter/NSwag/pull/2989

Was this page helpful?
0 / 5 - 0 ratings