微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 如何在json反序列化过程中忽略未知的枚举值?

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

当我基于当前文档创建枚举时,会发生这种情况,但第三方API稍后会添加更多枚举值.

我会很高兴将特殊值标记为未知或使用可空的枚举,而不匹配的值将返回null.

解决方法

您可以使用自定义JsonConverter解决此问题.这是一个我使用来自Json.Net的StringEnumConverter类中的几个集合.它应该给你灵活的处理事情,无论你决定什么.以下是它的工作原理:

>如果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)

原文地址:https://www.jb51.cc/csharp/93263.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐