加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 03:56:55 所属栏目:百科 来源:网络整理
导读:当我的枚举与json属性中提供的字符串值不匹配时,如何让Json.net不要抛出? 当我基于当前文档创建枚举时,会发生这种情况,但第三方API稍后会添加更多枚举值. 我会很高兴将特殊值标记为未知或使用可空的枚举,而不匹配的值将返回null. 解决方法 您可以使用自定义
当我的枚举与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)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读