You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何针对单个Web请求配置System.Text.Json的PropertyNamingPolicy

基于请求头切换System.Text.Json的命名规则(PascalCase/CamelCase)

问题背景

我们正将代码库从Newtonsoft.Json迁移至System.Text.Json,需实现根据Web请求的Accept头动态切换JSON命名规则:

  • 遗留ASP.NET网站发送application/json;case=default的Accept头,要求返回PascalCase格式的JSON
  • 新Angular网站使用默认的CamelCase格式

此前使用Newtonsoft.Json时,我们通过自定义输出格式化器实现该逻辑:

public class NewtonsoftJsonDefaultCaseFormatter : NewtonsoftJsonOutputFormatter
{
    public NewtonsoftJsonDefaultCaseFormatter(List<JsonConverter> converters) : base(new JsonSerializerSettings { ContractResolver = new DefaultContractResolver(), NullValueHandling = NullValueHandling.Include }, ArrayPool<char>.Shared, new MvcOptions(), new MvcNewtonsoftJsonOptions())
    {
        foreach (var converter in converters)
            SerializerSettings.Converters.Add(converter);
        SupportedMediaTypes.Clear();
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;case=default"));
    }
}

目前已在Startup中设置默认CamelCase序列化配置,但需要针对特定Accept头的请求切换为PascalCase:

var mvcBuilder = services
    .AddControllers()
    .AddJsonOptions(options => GetDefaultJsonOptions());

public static JsonSerializerOptions GetDefaultJsonOptions()
{
    var defaultOptions = new JsonSerializerOptions();
    defaultOptions.Converters.Add(new ConcurrentBagConverterFactory());
    defaultOptions.Converters.Add(new DateTimeConverter());
    defaultOptions.Converters.Add(DictionaryJsonConverterFactory.Default);
    defaultOptions.Converters.Add(new SqlGeographyConverter());
    defaultOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    defaultOptions.PropertyNameCaseInsensitive = true;
    defaultOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    defaultOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
    return defaultOptions;
}

解决方案

要在System.Text.Json中实现相同逻辑,需自定义SystemTextJsonOutputFormatter并注册到Mvc的格式化器集合中:

1. 自定义PascalCase输出格式化器

继承SystemTextJsonOutputFormatter,基于全局配置创建PascalCase的序列化选项,并指定仅支持目标Accept头:

public class PascalCaseJsonOutputFormatter : SystemTextJsonOutputFormatter
{
    public PascalCaseJsonOutputFormatter(JsonSerializerOptions baseOptions)
        : base(CreatePascalCaseOptions(baseOptions))
    {
        SupportedMediaTypes.Clear();
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;case=default"));
    }

    private static JsonSerializerOptions CreatePascalCaseOptions(JsonSerializerOptions baseOptions)
    {
        // 复制全局配置,避免修改原选项
        var pascalOptions = new JsonSerializerOptions(baseOptions);
        // 设置为PascalCase(null表示不修改属性名,保持原命名)
        pascalOptions.PropertyNamingPolicy = null;
        return pascalOptions;
    }
}

2. 在Startup中注册格式化器

修改Startup配置,添加自定义格式化器,确保ASP.NET Core能根据Accept头自动选择对应的序列化规则:

var mvcBuilder = services.AddControllers();

// 配置默认CamelCase序列化
mvcBuilder.AddJsonOptions(options => 
{
    var defaultOptions = GetDefaultJsonOptions();
    options.JsonSerializerOptions.Converters.AddRange(defaultOptions.Converters);
    options.JsonSerializerOptions.PropertyNamingPolicy = defaultOptions.PropertyNamingPolicy;
    options.JsonSerializerOptions.PropertyNameCaseInsensitive = defaultOptions.PropertyNameCaseInsensitive;
    options.JsonSerializerOptions.DefaultIgnoreCondition = defaultOptions.DefaultIgnoreCondition;
    options.JsonSerializerOptions.ReferenceHandler = defaultOptions.ReferenceHandler;
});

// 注册自定义PascalCase格式化器
mvcBuilder.AddMvcOptions(options =>
{
    var defaultJsonOptions = options.JsonSerializerOptions;
    options.OutputFormatters.Add(new PascalCaseJsonOutputFormatter(defaultJsonOptions));
});

public static JsonSerializerOptions GetDefaultJsonOptions()
{
    var defaultOptions = new JsonSerializerOptions();
    defaultOptions.Converters.Add(new ConcurrentBagConverterFactory());
    defaultOptions.Converters.Add(new DateTimeConverter());
    defaultOptions.Converters.Add(DictionaryJsonConverterFactory.Default);
    defaultOptions.Converters.Add(new SqlGeographyConverter());
    defaultOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    defaultOptions.PropertyNameCaseInsensitive = true;
    defaultOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    defaultOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
    return defaultOptions;
}

核心要点

  • 自定义格式化器通过复制全局JsonSerializerOptions继承所有转换器和配置,仅修改命名规则,保证配置一致性
  • 清除默认支持的媒体类型,仅响应application/json;case=default请求,避免干扰正常CamelCase请求
  • ASP.NET Core的内容协商机制会自动根据请求的Accept头匹配对应的输出格式化器,无需额外路由或逻辑判断

内容的提问来源于stack exchange,提问作者Justin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 05:03:38