【问题标题】:In Json.NET how to handle missing enum value to select another one instead在 Json.NET 中,如何处理缺少的枚举值以选择另一个枚举值
【发布时间】:2016-01-04 20:00:47
【问题描述】:

我想从我的枚举中删除一个枚举值。但是在反序列化 JSON 时,如果找到删除的枚举值,那么它应该选择我选择的枚举值,而不是默认为 None,这是我的枚举中的第一个值,以实现向后兼容性。

例子:

public enum ExampleHotkeyType
{
    None,
    CaptureRegion,
    CaptureRegionWindow,
    CaptureRegionPolygon,
    CaptureRegionFreehand
}

我想删除此枚举中的CaptureRegionWindow,并且在反序列化时如果发现CaptureRegionWindow 我希望将其分配给CaptureRegion。这样它就不会默认为None

我搜索了也许我可以将 CaptureRegion 枚举值设置为具有多个名称作为属性但找不到这样的东西。

处理此问题的最佳方法是什么,以便我的用户设置不会重置?

注意:我在序列化/反序列化时使用 StringEnumConverter。

【问题讨论】:

    标签: c# json enums json.net


    【解决方案1】:

    继承 StringEnumConverter 让我可以完全控制它:

    public class ExampleHotkeyTypeEnumConverter : StringEnumConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
            {
                string enumText = reader.Value.ToString();
    
                if (!string.IsNullOrEmpty(enumText) && enumText.Equals("CaptureRegionWindow"))
                {
                    return ExampleHotkeyType.CaptureRegion;
                }
            }
    
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
    }
    
    [JsonConverter(typeof(ExampleHotkeyTypeEnumConverter))]
    public enum ExampleHotkeyType
    {
        None,
        CaptureRegion,
        CaptureRegionWindow,
        CaptureRegionPolygon,
        CaptureRegionFreehand
    }
    

    如果您想保留现有的枚举值,则可以使用此枚举转换器:

    public class SafeStringEnumConverter : StringEnumConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            try
            {
                return base.ReadJson(reader, objectType, existingValue, serializer);
            }
            catch (JsonSerializationException)
            {
                return existingValue;
            }
        }
    }
    

    【讨论】:

    • 作为一个通用解决方案,我建议创建类似于 .NET EnumMember 的属性,它可以接受多个值,然后在反序列化阶段使用它——这样我们就可以支持任意枚举。这是支持EnumMember属性的转换器。 gist.github.com/gubenkoved/999eb73e227b7063a67a50401578c3a7
    猜你喜欢
    • 2019-01-29
    • 2017-04-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多