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

.NET 5.0中如何为单个控制器配置Newtonsoft Json枚举字符串序列化

你原来两次调用services.AddMvc().AddNewtonsoftJson()的方式行不通,第二次调用会直接覆盖第一次的全局配置,没法实现“两组配置并存”的效果。下面给你几个实用的解决方案:

方案一:自定义JsonResult(最直接省心)

先创建一个专属的JsonResult类型,内置带StringEnumConverter的序列化配置:

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class StringEnumJsonResult : JsonResult
{
    // 提前定义好固定配置,避免重复创建
    private static readonly JsonSerializerSettings _customSettings = new JsonSerializerSettings
    {
        DateTimeZoneHandling = DateTimeZoneHandling.Utc,
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        DateFormatString = "yyyy-MM-ddTHH:mm:ssK",
        Converters = { new StringEnumConverter() }
    };

    public StringEnumJsonResult(object value) : base(value)
    {
        SerializerSettings = _customSettings;
    }
}

然后在需要特殊处理的控制器Action里,返回这个自定义结果就行:

public class SpecialController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        var data = new { Status = MyEnum.Active, CreateTime = DateTime.Now };
        return new StringEnumJsonResult(data);
    }
}

其他控制器正常用默认的Json()方法,全局配置保持你最初的默认设置:

services.AddMvc().AddNewtonsoftJson(options =>
{
    options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
    options.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
    options.SerializerSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ssK";
});
方案二:用Action过滤器(不用改Action返回类型)

如果不想改Action的返回写法,可以写个过滤器自动替换序列化配置:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class UseStringEnumSerializationAttribute : ActionFilterAttribute
{
    private static readonly JsonSerializerSettings _customSettings = new JsonSerializerSettings
    {
        DateTimeZoneHandling = DateTimeZoneHandling.Utc,
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        DateFormatString = "yyyy-MM-ddTHH:mm:ssK",
        Converters = { new StringEnumConverter() }
    };

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is JsonResult jsonResult)
        {
            // 直接替换默认的序列化配置
            jsonResult.SerializerSettings = _customSettings;
        }
        base.OnResultExecuting(context);
    }
}

接着在目标控制器或者单个Action上标记这个特性:

// 给整个控制器加,里面所有Action都会用字符串枚举序列化
[UseStringEnumSerialization]
public class SpecialController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        var data = new { Status = MyEnum.Active, CreateTime = DateTime.Now };
        return Json(data); // 还是写默认的Json方法,过滤器会自动处理
    }
}

全局配置同样保持默认即可。

方案三:注入不同配置的序列化器(灵活度最高)

如果需要更灵活的控制,可以把两组配置都注册到DI容器,然后在控制器里按需取用:

先在Startup.cs里注册两个配置:

// 默认配置
services.AddSingleton<JsonSerializerSettings>(sp => new JsonSerializerSettings
{
    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateFormatString = "yyyy-MM-ddTHH:mm:ssK"
});

// 带字符串枚举的配置,给个名字区分
services.AddSingleton<JsonSerializerSettings>("StringEnum", sp => new JsonSerializerSettings
{
    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateFormatString = "yyyy-MM-ddTHH:mm:ssK",
    Converters = { new StringEnumConverter() }
});

然后在目标控制器里注入命名的配置,手动序列化后返回:

public class SpecialController : ControllerBase
{
    private readonly JsonSerializerSettings _stringEnumSettings;

    // 通过构造函数注入指定名称的配置
    public SpecialController([FromKeyedServices("StringEnum")] JsonSerializerSettings stringEnumSettings)
    {
        _stringEnumSettings = stringEnumSettings;
    }

    [HttpGet]
    public IActionResult GetData()
    {
        var data = new { Status = MyEnum.Active, CreateTime = DateTime.Now };
        var json = JsonConvert.SerializeObject(data, _stringEnumSettings);
        return Content(json, "application/json");
    }
}

如果.NET 5里[FromKeyedServices]用不了,就封装个工厂类来获取配置:

public class JsonSettingsFactory
{
    private readonly IServiceProvider _serviceProvider;

    public JsonSettingsFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public JsonSerializerSettings GetDefaultSettings()
    {
        return _serviceProvider.GetRequiredService<JsonSerializerSettings>();
    }

    public JsonSerializerSettings GetStringEnumSettings()
    {
        return _serviceProvider.GetRequiredService<JsonSerializerSettings>("StringEnum");
    }
}

// 别忘了在Startup.cs注册工厂
services.AddSingleton<JsonSettingsFactory>();

之后控制器注入工厂就行:

public class SpecialController : ControllerBase
{
    private readonly JsonSerializerSettings _stringEnumSettings;

    public SpecialController(JsonSettingsFactory settingsFactory)
    {
        _stringEnumSettings = settingsFactory.GetStringEnumSettings();
    }

    // 后续代码和上面一样
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 11:52:52