C# 在ASP.NET Core 3中,是否有一种内置的方式使用snake case作为JSON的命名策略?

C# 在ASP.NET Core 3中,是否有一种内置的方式使用snake case作为JSON的命名策略?,c#,asp.net-core,.net-core,.net-core-3.0,system.text.json,C#,Asp.net Core,.net Core,.net Core 3.0,System.text.json,我使用以下代码成功地使其工作: .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }; }); 然而,这使得MVC使用Newtonsoft而不是System.Text.JSON,后者更快、异步

我使用以下代码成功地使其工作:

.AddNewtonsoftJson(options => {
    options.SerializerSettings.ContractResolver = new DefaultContractResolver
    {
        NamingStrategy = new SnakeCaseNamingStrategy()
    };
});
然而,这使得MVC使用
Newtonsoft
而不是
System.Text.JSON
,后者更快、异步且内置


查看
System.Text.JSON
中的命名策略选项,我只能找到CamelCase。snake case是否有本机支持?实现snake-case JSON命名风格的更好方法是什么?

目前还没有对snake-case的内置支持,
但是
.NET Core 3.0
允许通过继承来设置自定义命名策略

您需要使用snake-case转换实现
ConvertName
方法。
(Newtonsoft Json.NET有一个内部类,显示如何处理此问题。)


下面的POC实现仅在蛇壳转换中重新使用Json.NET的
SnakeCaseNamingStrategy
(,而整个应用程序使用
System.Text.Json

最好不要只依赖Newtonsoft Json.Net进行蛇形转换,但在下面这个相当懒惰的示例中,我不想重新思考/重新发明蛇形转换方法。
这个答案的要点是如何钩住自定义策略(而不是snake-case转换本身)。
(有许多库,展示了如何钩住自定义策略。)

Startup.cs
中应用此自定义
SnakeCaseNamingPolicy

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()            
        .AddJsonOptions(
            options => { 
                options.JsonSerializerOptions.PropertyNamingPolicy = 
                    SnakeCaseNamingPolicy.Instance;
            });
}

下面的类的实例

public class WeatherForecast
{
    public DateTime Date { get; set; }

    public int TemperatureCelcius { get; set; }

    public int TemperatureFahrenheit { get; set; }

    [JsonPropertyName("Description")]
    public string Summary { get; set; }
}
将有一个
Json
表示,如下所示:

{ "date" : "2019-10-28T01:00:56.6498885+01:00",
  "temperature_celcius" : 48,
  "temperature_fahrenheit" : 118,
  "Description" : "Cool"
}
请注意,属性
摘要
已命名为
说明


匹配其
System.Text.Json.Serialization.JsonPropertyNameAttribute

只需在pfx代码中稍加修改,即可删除对
Newtonsoft Json.Net
的依赖

String
extension-mentod将给定字符串转换为
SnakeCase

public static class StringUtils
{
    public static string ToSnakeCase(this string str)
    {
        return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
    }
}
然后在我们的SnakeCaseNamingPolicy中

public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
    public static SnakeCaseNamingPolicy Instance { get; } = new SnakeCaseNamingPolicy();

    public override string ConvertName(string name)
    {
        // Conversion to other naming convention goes here. Like SnakeCase, KebabCase etc.
        return name.ToSnakeCase();
    }
}
最后一步是在
Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()            
        .AddJsonOptions(
            options => { 
                options.JsonSerializerOptions.PropertyNamingPolicy = 
                    SnakeCaseNamingPolicy.Instance;
            });
}
使用该模型:

public class WeatherForecast
{
    public DateTime Date { get; set; }

    public int TemperatureCelcius { get; set; }

    public int TemperatureFahrenheit { get; set; }

    public string Summary { get; set; }
}
Json
输出:

{
  "date": "2019-10-28T08:26:14.878444+05:00",
  "temperature_celcius": 4,
  "temperature_fahrenheit": 0,
  "summary": "Scorching"
}

我在这里分享@pfx解决方案的完整实现。自定义命名策略(从NewtonSoft复制):

以及示例用法:

var data = new TestSerializer();
data.TimeStamp = DateTime.Now;
data.CPUPower = 10;

var serializeOptions = new JsonSerializerOptions 
{
    PropertyNamingPolicy = new SnakeCaseNamingPolicy()
};
var json_string = JsonSerializer.Serialize(data, serializeOptions);
Console.WriteLine(json_string);

给出
{“时间戳”:“2020-08-06T00:30:35.3815583-04:00”,“cpu电源”:10}

这有点晚了,但此解决方案也将解决类似ABCItem或MyCPU的情况。 这只是一个概念,您可以对其进行改进,使其更加通用

using System.Collections.Generic;

namespace Extensions
{
    public static class StringExtension
    {
        public static string ToSnakeCase(this string str)
        {
            // collect the final result
            var snakeCase = new List<char>();

            // check and add chars (using for loop for performance)
            for (int i = 0; i < str.Length; i++)
            {
                if (i > 0 && char.IsUpper(str[i]) && !char.IsUpper(str[i + 1]))
                {
                    snakeCase.Add('_');
                }
                snakeCase.Add(str[i]);
            }

            // build the new string
            return new string(snakeCase.ToArray()).ToLower();
        }
    }
}

var snakeCase = "CPUMeter".ToSnakeCase();
var snakeCase = "PascalCase".ToSnakeCase();
var snakeCase = "camelCase".ToSnakeCase();
使用System.Collections.Generic;
命名空间扩展
{
公共静态类扩展
{
公共静态字符串ToSnakeCase(此字符串str)
{
//收集最终结果
var snakeCase=新列表();
//检查并添加字符(使用for循环提高性能)
对于(int i=0;i0&&char.IsUpper(str[i])&&&char.IsUpper(str[i+1]))
{
蛇壳。加上(“);
}
添加(str[i]);
}
//构建新字符串
返回新字符串(snakeCase.ToArray()).ToLower();
}
}
}
var snakeCase=“CPUMeter”.ToSnakeCase();
var snakeCase=“PascalCase”.ToSnakeCase();
var snakeCase=“camelCase”.ToSnakeCase();

这是一个存储库,其中包含
SnakeCase
KebabCase
NamingPolicy,用于
System.Text.Json

JsonSnakeCaseNamingPolicy

var options = new JsonSerializerOptions() { PropertyNamingPolicy = new JsonSnakeCaseNamingPolicy() };
var person = new Person() { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var json = JsonSerializer.Serialize(person, options);
var options = new JsonSerializerOptions() { PropertyNamingPolicy = new JsonKebabCaseNamingPolicy() };
var person = new Person() { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var json = JsonSerializer.Serialize(person, options);
JsonKebabCaseNamingPolicy

var options = new JsonSerializerOptions() { PropertyNamingPolicy = new JsonSnakeCaseNamingPolicy() };
var person = new Person() { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var json = JsonSerializer.Serialize(person, options);
var options = new JsonSerializerOptions() { PropertyNamingPolicy = new JsonKebabCaseNamingPolicy() };
var person = new Person() { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var json = JsonSerializer.Serialize(person, options);

我认为asp.NETCore是开箱即用的。不需要额外的配置。我错了吗?它不做蛇的案子,它默认做骆驼的案子,事实上它没有错。C#属性命名约定为。因此,CPU被认为是三个不同的词。您可以使用两种解决方案,一种是使用
[JsonPropertyName(“CPU\u power”)]
,另一种是将属性名称更改为
CpuPower
var options = new JsonSerializerOptions() { PropertyNamingPolicy = new JsonKebabCaseNamingPolicy() };
var person = new Person() { FirstName = "Jorge", Birthday = DateTime.UtcNow, MyJobCity = "Madrid" };
var json = JsonSerializer.Serialize(person, options);