当我的枚举与json属性中提供的字符串值不匹配时,如何使Json.net不抛出?
当我根据当前文档创建枚举时会发生这种情况,但是第三方API稍后会添加更多的枚举值。
我很高兴将特殊值标记为Unknown或使用可为空的枚举,并且不匹配的值将返回null。
您可以使用custom解决此问题JsonConverter。这是我使用StringEnumConverter来自Json.Net 的类中的一些片段组合而成的。它应该使您能够灵活地以各种方式处理事情。运作方式如下:
JsonConverter
StringEnumConverter
这是代码。随时更改它以满足您的需求。
class TolerantEnumConverter : JsonConverter { public override bool CanConvert(Type objectType) { Type type = IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType; return type.IsEnum; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { bool isNullable = IsNullableType(objectType); Type enumType = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; string[] names = Enum.GetNames(enumType); if (reader.TokenType == JsonToken.String) { string enumText = reader.Value.ToString(); if (!string.IsNullOrEmpty(enumText)) { string match = names .Where(n => string.Equals(n, enumText, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (match != null) { return Enum.Parse(enumType, match); } } } else if (reader.TokenType == JsonToken.Integer) { int enumVal = Convert.ToInt32(reader.Value); int[] values = (int[])Enum.GetValues(enumType); if (values.Contains(enumVal)) { return Enum.Parse(enumType, enumVal.ToString()); } } if (!isNullable) { string defaultName = names .Where(n => string.Equals(n, "Unknown", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (defaultName == null) { defaultName = names.First(); } return Enum.Parse(enumType, defaultName); } return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteValue(value.ToString()); } private bool IsNullableType(Type t) { return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)); } }
这是一个演示,它使用几个不同的枚举使转换器按照自己的步调前进(一个具有“未知”值,另一个没有):
[JsonConverter(typeof(TolerantEnumConverter))] enum Status { Ready = 1, Set = 2, Go = 3 } [JsonConverter(typeof(TolerantEnumConverter))] enum Color { Red = 1, Yellow = 2, Green = 3, Unknown = 99 } class Foo { public Status NonNullableStatusWithValidStringValue { get; set; } public Status NonNullableStatusWithValidIntValue { get; set; } public Status NonNullableStatusWithInvalidStringValue { get; set; } public Status NonNullableStatusWithInvalidIntValue { get; set; } public Status NonNullableStatusWithNullValue { get; set; } public Status? NullableStatusWithValidStringValue { get; set; } public Status? NullableStatusWithValidIntValue { get; set; } public Status? NullableStatusWithInvalidStringValue { get; set; } public Status? NullableStatusWithInvalidIntValue { get; set; } public Status? NullableStatusWithNullValue { get; set; } public Color NonNullableColorWithValidStringValue { get; set; } public Color NonNullableColorWithValidIntValue { get; set; } public Color NonNullableColorWithInvalidStringValue { get; set; } public Color NonNullableColorWithInvalidIntValue { get; set; } public Color NonNullableColorWithNullValue { get; set; } public Color? NullableColorWithValidStringValue { get; set; } public Color? NullableColorWithValidIntValue { get; set; } public Color? NullableColorWithInvalidStringValue { get; set; } public Color? NullableColorWithInvalidIntValue { get; set; } public Color? NullableColorWithNullValue { get; set; } } class Program { static void Main(string[] args) { string json = @" { ""NonNullableStatusWithValidStringValue"" : ""Set"", ""NonNullableStatusWithValidIntValue"" : 2, ""NonNullableStatusWithInvalidStringValue"" : ""Blah"", ""NonNullableStatusWithInvalidIntValue"" : 9, ""NonNullableStatusWithNullValue"" : null, ""NullableStatusWithValidStringValue"" : ""Go"", ""NullableStatusWithValidIntValue"" : 3, ""NullableStatusWithNullValue"" : null, ""NullableStatusWithInvalidStringValue"" : ""Blah"", ""NullableStatusWithInvalidIntValue"" : 9, ""NonNullableColorWithValidStringValue"" : ""Green"", ""NonNullableColorWithValidIntValue"" : 3, ""NonNullableColorWithInvalidStringValue"" : ""Blah"", ""NonNullableColorWithInvalidIntValue"" : 0, ""NonNullableColorWithNullValue"" : null, ""NullableColorWithValidStringValue"" : ""Yellow"", ""NullableColorWithValidIntValue"" : 2, ""NullableColorWithNullValue"" : null, ""NullableColorWithInvalidStringValue"" : ""Blah"", ""NullableColorWithInvalidIntValue"" : 0, }"; Foo foo = JsonConvert.DeserializeObject<Foo>(json); foreach (PropertyInfo prop in typeof(Foo).GetProperties()) { object val = prop.GetValue(foo, null); Console.WriteLine(prop.Name + ": " + (val == null ? "(null)" : val.ToString())); } } }
输出:
NonNullableStatusWithValidStringValue: Set NonNullableStatusWithValidIntValue: Set NonNullableStatusWithInvalidStringValue: Ready NonNullableStatusWithInvalidIntValue: Ready NonNullableStatusWithNullValue: Ready NullableStatusWithValidStringValue: Go NullableStatusWithValidIntValue: Go NullableStatusWithInvalidStringValue: (null) NullableStatusWithInvalidIntValue: (null) NullableStatusWithNullValue: (null) NonNullableColorWithValidStringValue: Green NonNullableColorWithValidIntValue: Green NonNullableColorWithInvalidStringValue: Unknown NonNullableColorWithInvalidIntValue: Unknown NonNullableColorWithNullValue: Unknown NullableColorWithValidStringValue: Yellow NullableColorWithValidIntValue: Yellow NullableColorWithInvalidStringValue: (null) NullableColorWithInvalidIntValue: (null) NullableColorWithNullValue: (null)