Skip to content

OpenApi convert to snackcase #60513

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

Closed
1 task done
codewithmecoder opened this issue Feb 20, 2025 · 7 comments
Closed
1 task done

OpenApi convert to snackcase #60513

codewithmecoder opened this issue Feb 20, 2025 · 7 comments
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved

Comments

@codewithmecoder
Copy link

codewithmecoder commented Feb 20, 2025

Is there an existing issue for this?

  • I have searched the existing issues

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

Microsoft.AspNetCore.OpenApi 9.0.2

builder.Services.AddOpenApi(options =>
{
    
    options.AddHeader("os", "ios");
    options.AddHeader("lang", "en");
    options.AddHeader("appearance", "1");
    options.AddDocumentTransformer((doc, _, _) =>
    {
        doc.Info = new OpenApiInfo
        {
            Title = "Mobile User Setting API",
            Version = "v1",
            Description = "API for get user general settings."
        };
        return Task.CompletedTask;
    });
});

Describe the solution you'd like

I want request and response in snackcase.

Additional context

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Feb 20, 2025
@martincostello
Copy link
Member

Use ConfigureHttpJsonOptions() to enable snake case naming for your endpoints' JSON serialization.

@martincostello martincostello added feature-openapi ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. labels Feb 20, 2025
@codewithmecoder
Copy link
Author

Hi @martincostello, thank you for your response.
I am working on a project with .NET9 and use Scalar for documentation UI Microsoft OpenApi. I applied Newtonsoft for json Serialize and Deserialize. For response I got snackcase but for request I got camelcase in Scalar UI. How can I configure it to snackcase in request?

Thanks

@martincostello
Copy link
Member

You would configure the OpenAPI document to use snake case in the way I already described.

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
});

However, note that Microsoft.AspNetCore.OpenApi does not support Newtonsoft.Json. See #60458 for more details.

@codewithmecoder
Copy link
Author

You would configure the OpenAPI document to use snake case in the way I already described.

builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
});
However, note that Microsoft.AspNetCore.OpenApi does not support Newtonsoft.Json. See #60458 for more details.

Thank you 🙏 and noted

@codewithmecoder
Copy link
Author

codewithmecoder commented Feb 21, 2025

builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory());
}).AddJsonOptions(options =>
{
    options.JsonSerializerOptions.PropertyNamingPolicy = new JsonSerializerSnakeCaseNamingPolicy();
    options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.JsonSerializerOptions.WriteIndented = false;
    options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = new JsonSerializerSnakeCaseNamingPolicy();
    options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.SerializerOptions.WriteIndented = false;
    options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
public class JsonSerializerSnakeCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name)
    {
        return name.ToSnakeCase();
    }
}

public static string ToSnakeCase(this string o) =>
    SnakeCase().Replace(o, "$1_$2").ToLower();

[GeneratedRegex(@"(\w)([A-Z])")]
private static partial Regex SnakeCase();

This get to work, but this could be improve?

@martincostello
Copy link
Member

Add a method to configure the options so you don't repeat it:

builder.Services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory());
}).AddJsonOptions(options => ConfigureJsonSerializer(options.JsonSerializerOptions));

builder.Services.ConfigureHttpJsonOptions(options => ConfigureJsonSerializer(options.SerializerOptions));

static void ConfigureJsonSerializer(JsonSerializerOptions options)
{
    options.PropertyNamingPolicy = new JsonSerializerSnakeCaseNamingPolicy();
    options.Converters.Add(new JsonStringEnumConverter());
    options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.WriteIndented = false;
    options.ReferenceHandler = ReferenceHandler.IgnoreCycles;
}

For the second snippet, use the built-in snake case options I already linked you to (JsonNamingPolicy.SnakeCaseLower).

Copy link
Contributor

This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.

See our Issue Management Policies for more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved
Projects
None yet
Development

No branches or pull requests

2 participants