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

.NET 3.1中Json序列化未定义枚举值不报错的优雅解决方法

.NET 3.1下枚举非法值的校验方案

针对.NET 3.1中枚举绑定非法值时自动设为默认值的问题,以下是几种更优雅的解决方式:

1. 自定义Json转换器(适配JSON请求体)

因为接口使用[FromBody]接收JSON数据,可给枚举类型添加自定义JsonConverter,在反序列化阶段校验值的合法性:

public class StrictEnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum
{
    public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var valueStr = reader.GetString();
        if (!Enum.TryParse<TEnum>(valueStr, ignoreCase: false, out var result) || !Enum.IsDefined(typeof(TEnum), result))
        {
            throw new JsonException($"无效的枚举值:{valueStr},允许的值为:{string.Join(", ", Enum.GetNames(typeof(TEnum)))}");
        }
        return result;
    }

    public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

给枚举类添加特性指定转换器:

[JsonConverter(typeof(StrictEnumConverter<ChangeTime>))]
public enum ChangeTime
{
   Immediate, Later
}

当传入非法值时,系统会抛出JsonException,自动返回400 Bad Request响应,无需手动处理。

2. 自定义验证属性

创建验证属性标记在枚举字段上,在模型验证阶段校验值的合法性:

public class ValidEnumValueAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return ValidationResult.Success; // 若不允许空值,可返回对应错误
        }

        var enumType = value.GetType();
        if (!Enum.IsDefined(enumType, value))
        {
            return new ValidationResult($"值 {value} 不是有效的 {enumType.Name} 枚举值,允许的值为:{string.Join(", ", Enum.GetNames(enumType))}");
        }
        return ValidationResult.Success;
    }
}

在Request类的字段上添加该属性:

public class Request
{
    [ValidEnumValue]
    public ChangeTime ChangeTime { get; set; }
}

在接口中判断模型验证状态:

[HttpPost("test")]
public async Task<ActionResult> Post([FromBody]Request request)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // 后续业务逻辑
}

3. 全局配置严格枚举校验(适配所有枚举)

若希望所有枚举都启用严格校验,可在Startup.cs的ConfigureServices中全局配置Json序列化选项:

services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 遍历当前程序集所有枚举类型,添加严格转换器
        foreach (var enumType in Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsEnum))
        {
            var converterType = typeof(StrictEnumConverter<>).MakeGenericType(enumType);
            options.JsonSerializerOptions.Converters.Add((JsonConverter)Activator.CreateInstance(converterType));
        }
    });

这样所有枚举都会自动应用严格校验,无需逐个添加特性。

以上方案均优于改为string手动校验的方式,性能损耗可忽略,同时能准确拦截非法枚举值并返回合适的错误响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:20:55