自定义EnumConverter未按预期返回默认枚举值的问题排查
问题分析与解决方案
咱们先直击核心问题:当传入数字7时转换器没返回MyEnum.Unknown,问题出在Number分支的判断逻辑完全走偏了。
为什么数字7不会返回Unknown?
看你Number分支的代码:
var value = reader.GetInt32(); MyEnum myEnum = (MyEnum)value; if (Enum.TryParse(typeToConvert, myEnum.ToString(), out var result)) { return (MyEnum)result; } return MyEnum.Unknown;
这里的逻辑漏洞很明显:
- C#允许把任意符合底层类型范围的数值强转成枚举,所以
(MyEnum)7会得到一个未在枚举定义里的“非法”枚举实例。 - 把这个实例转成字符串会得到
"7",而Enum.TryParse默认允许解析数字字符串——哪怕这个数字不在枚举的定义值里,它也会成功返回对应的枚举实例(也就是(MyEnum)7),根本不会进入返回Unknown的分支。
说白了,你这里的TryParse判断完全起不到“验证枚举是否为有效值”的作用。
正确的修复方案:用Enum.IsDefined做有效性校验
应该直接检查传入的数字是否是枚举的已定义有效值,修改后的完整转换器代码如下:
public override MyEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { case JsonTokenType.String: { var value = reader.GetString(); // 先尝试解析,再验证是否为已定义的枚举成员 if (Enum.TryParse(typeToConvert, value, out MyEnum result) && Enum.IsDefined(typeToConvert, result)) { return result; } return MyEnum.Unknown; } case JsonTokenType.Number: { var value = reader.GetInt32(); // 直接验证数值是否在枚举的已定义值范围内 if (Enum.IsDefined(typeToConvert, value)) { return (MyEnum)value; } return MyEnum.Unknown; } default: return MyEnum.Unknown; } }
额外补充说明
- 我给String分支也加上了
Enum.IsDefined判断——因为默认Enum.TryParse同样会解析数字格式的字符串(比如传入"7"的字符串,原来的代码会返回(MyEnum)7而不是Unknown),加上校验后才能确保只有枚举定义的字符串值(比如"FirstEnum")才会被正确解析。 Enum.IsDefined会严格检查传入的数值/枚举实例是否是枚举中显式定义的成员,能彻底过滤掉所有未定义的非法值。
测试验证
修改后再跑你的测试场景:
- 传入
{"myType": 7}:Enum.IsDefined返回false,返回MyEnum.Unknown,符合预期。 - 传入
{"myType": "Random"}:Enum.TryParse失败,返回MyEnum.Unknown,正常。 - 传入
{"myType": 1}:Enum.IsDefined返回true,返回MyEnum.FirstEnum,正常。
内容的提问来源于stack exchange,提问作者user7849697
相关产品推荐
相关产品推荐

