我如何在json反序列化期间忽略未知的枚举值?

当我的枚举与json属性中提供的字符串值不匹配时,如何使Json.net不抛出?

当我根据当前文档创建枚举时会发生这种情况,但是第三方API稍后会添加更多的枚举值。

我很高兴将特殊值标记为Unknown或使用可为空的枚举,并且不匹配的值将返回null。

回答:

您可以使用custom解决此问题JsonConverter。这是我使用StringEnumConverter来自Json.Net

的类中的一些片段组合而成的。它应该使您能够灵活地以各种方式处理事情。运作方式如下:

  • 如果在JSON中找到的值与枚举匹配(作为字符串或整数),则使用该值。(如果值是整数,并且有多个可能的匹配项,则使用第一个。)
  • 否则,如果枚举类型为可为空,则将该值设置为null。
  • 否则,如果枚举具有一个名为“未知”的值,则将使用该值。
  • 否则,将使用枚举的第一个值。

这是代码。随时更改它以满足您的需求。

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)

以上是 我如何在json反序列化期间忽略未知的枚举值? 的全部内容, 来源链接: utcz.com/qa/403904.html

回到顶部