提问人:Kounavi 提问时间:11/15/2023 更新时间:11/16/2023 访问量:72
System.Text.Json:序列化数据时如何强制执行默认的 camelCase JsonNamingPolicy?
System.Text.Json: How can I enforce default camelCase JsonNamingPolicy when Serializing data?
问:
我有一个烦人的问题,当我添加自定义JSON转换器时,在反序列化属性时不遵守命名策略。无论如何,它始终默认为 PascalCase。
我还可以使用 .NET 6 使用最小的 Web API 复制它。
程序.cs
using System.Text.Json;
using Microsoft.AspNetCore.Http.Json;
using MinimalWebApi.Converters;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddMvc();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<JsonOptions>(
options => {
options.SerializerOptions.Converters.Add(new FooModelJsonConverter());
//NOTE: This is the default policy but enabling it does not make a difference.
//options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
}
);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
FooModelJsonConverter.cs
using System.Text.Json;
using System.Text.Json.Serialization;
using MinimalWebApi.Model;
namespace MinimalWebApi.Converters;
public class FooModelJsonConverter: JsonConverter<FooModel>
{
public override FooModel Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options
)
{
return
JsonSerializer.Deserialize<FooModel>(ref reader, options)
?? throw new JsonException("FooModel could not be deserialized as it was null!");
}
public override void Write(
Utf8JsonWriter writer,
FooModel fooModel,
JsonSerializerOptions options
) {
writer.WriteStartObject();
var majorVersion = fooModel.MajorVersion;
var minorVersion = fooModel.MinorVersion;
if (majorVersion == null || minorVersion == null)
throw new JsonException(
$"Expected a 'Major' & 'Minor' attribute but one (or both) of them is null => MajorVersion: {majorVersion}\nMinorVersion: {minorVersion}!"
);
switch (majorVersion)
{
case 1:
writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Id), options, true));
JsonSerializer.Serialize(writer, fooModel.Id, options);
switch (minorVersion)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.AnotherId), options, true));
JsonSerializer.Serialize(writer, fooModel.AnotherId, options);
break;
default:
throw new JsonException($"Unexpected 'Minor' version attribute: {minorVersion}");
}
writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Name), options, true));
JsonSerializer.Serialize(writer, fooModel.Name, options);
writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Status), options, true));
JsonSerializer.Serialize(writer, fooModel.Status, options);
break;
default:
throw new JsonException($"Unexpected 'Major' version attribute: {majorVersion}");
}
writer.WriteEndObject();
}
public static string TryParseCamelCase(string propertyName, JsonSerializerOptions options, bool disabled = false)
{
var namingPolicy = options.PropertyNamingPolicy;
if (!disabled)
return namingPolicy != null ? namingPolicy.ConvertName(propertyName) : propertyName;
else
return propertyName;
}
}
FooModel.cs
using System.Text.Json.Serialization;
using MinimalWebApi.Converters;
namespace MinimalWebApi.Model
{
[JsonConverter(typeof(FooModelJsonConverter))]
public class FooModel
{
public enum State { STARTED, RUNNING, COMPLETED, FAILED };
public Guid Id { get; set; }
public string? AnotherId { get; set; }
public string? Name { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public State Status { get; set; }
[JsonIgnore]
public int? MajorVersion { get; set; } = 1;
[JsonIgnore]
public int? MinorVersion { get; set; } = 0;
}
}
如您所见,我找到了一种解决方法,即从 .但是,我想知道如何强制我的控制器正确序列化它?
请注意,我已尝试在添加服务时显式指定 CamelCase 选项(请参阅上面的代码;Program.cs),在我的自定义中创建一个新实例,并在我的控制器中指定一个显式,但这些不起作用。有人对此有什么想法吗?ConvertName
PropertyNamingPolicy
JsonSerializerOptions
FooModelJsonConverter
ActionResult
PS:这篇 SO 帖子声称我们应该使用而不是在下面的响应/评论中进一步建议配置它们,因为 Swashbuckle 将无法正确解析 JSON 响应正文。但是,我怀疑这是否正确和/或有意义。using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.Json;
答:
0赞
Kounavi
11/16/2023
#1
根据 GH-31818 问题:JsonConverter 中的 WritePropertyName 不考虑大小写,这是预期行为,因此我必须从相应的 JsonNamingPolicy 中显式调用 ConvertName。
评论
JsonSerializerOptions
JsonSerializer.Serialize(payload, options)
JsonSerializer.Deserialize<FooModel>(jsonString, options);
[JsonConverter(typeof(FooModelJsonConverter))]
nameof(fooModel.Id)
TryParseCamelCase
disabled == true