.NET 6 Web API添加自定义JsonConverter后驼峰命名失效求助
.NET 6 Minimal Web API自定义JSON转换器后CamelCase命名策略失效问题解决
问题描述
在.NET 6的Minimal Web API中添加自定义JSON转换器后,序列化/反序列化属性不再遵循默认的CamelCase命名策略,始终输出PascalCase格式。目前已通过显式调用PropertyNamingPolicy.ConvertName方法临时解决,但希望找到让控制器自动遵循命名策略的方案。
已尝试但无效的操作:
- 服务配置阶段显式指定
JsonNamingPolicy.CamelCase - 在自定义
FooModelJsonConverter内创建新的JsonSerializerOptions实例 - 控制器中返回显式
ActionResult<T>类型
相关代码
Program.cs
using System.Text.Json; using Microsoft.AspNetCore.Http.Json; using MinimalWebApi.Converters; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddMvc(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.Configure<JsonOptions>( options => { options.SerializerOptions.Converters.Add(new FooModelJsonConverter()); // 显式设置也无效果 //options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; } ); var app = builder.Build(); 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反序列化为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($"缺少Major/Minor属性,当前值:MajorVersion: {majorVersion}, MinorVersion: {minorVersion}"); switch (majorVersion) { case 1: writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Id), options, true)); JsonSerializer.Serialize(writer, fooModel.Id, options); switch (minorVersion) { case 3: writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.AnotherId), options, true)); JsonSerializer.Serialize(writer, fooModel.AnotherId, options); break; case 0: case 1: case 2: break; default: throw new JsonException($"未知Minor版本:{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($"未知Major版本:{majorVersion}"); } writer.WriteEndObject(); } public static string TryParseCamelCase(string propertyName, JsonSerializerOptions options, bool disabled = false) { var namingPolicy = options.PropertyNamingPolicy; return !disabled && namingPolicy != null ? namingPolicy.ConvertName(propertyName) : 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; } }
解决方案
1. 修复转换器中的命名策略开关
当前代码中调用TryParseCamelCase时传入了disabled=true,直接跳过了命名策略转换,这是PascalCase输出的核心原因。修改Write方法中所有WritePropertyName的调用,将最后一个参数改为false:
// 原代码 writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Id), options, true)); // 修改后 writer.WritePropertyName(TryParseCamelCase(nameof(fooModel.Id), options, false));
修改后,转换器会自动使用配置的CamelCase命名策略生成属性名。
2. 配置正确的JSON选项类
你使用了MapControllers(),属于MVC控制器体系,而Microsoft.AspNetCore.Http.Json.JsonOptions是为纯Minimal API的端点路由设计的,两者不兼容。需要替换命名空间并配置MVC的JsonOptions:
替换Program.cs中的using语句:
// 移除 // using Microsoft.AspNetCore.Http.Json; // 添加 using Microsoft.AspNetCore.Mvc;修改配置代码:
builder.Services.Configure<JsonOptions>( options => { options.JsonSerializerOptions.Converters.Add(new FooModelJsonConverter()); options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; } );
这就是StackOverflow帖子建议替换命名空间的原因——选错配置类会导致所有JSON设置失效。
3. 优化转换器实现(可选)
如果不需要手动拼接JSON,可以利用匿名类结合版本逻辑,让JsonSerializer自动处理命名策略,简化代码:
public override void Write(Utf8JsonWriter writer, FooModel fooModel, JsonSerializerOptions options) { var serializedObj = fooModel.MajorVersion switch { 1 => fooModel.MinorVersion switch { 0 or 1 or 2 => new { fooModel.Id, fooModel.Name, fooModel.Status }, 3 => new { fooModel.Id, fooModel.AnotherId, fooModel.Name, fooModel.Status }, _ => throw new JsonException($"未知Minor版本:{fooModel.MinorVersion}") }, _ => throw new JsonException($"未知Major版本:{fooModel.MajorVersion}") }; JsonSerializer.Serialize(writer, serializedObj, options); }
这种方式完全依赖框架的序列化逻辑,无需手动处理属性名转换,更不易出错。
内容的提问来源于stack exchange,提问作者Kounavi
相关产品推荐
相关产品推荐

