使用Json.Net进行C#枚举反序列化:将值转换为类型时出错

Min*_*amy 15 .net c# json json.net deserialization

我正在使用Json.NET来序列化/反序列化一些JSON API.

API响应具有一些整数值,这些值映射到应用程序中定义的枚举.

枚举是这样的:

public enum MyEnum
    {
        Type1,
        Type2,
        Type3
}
Run Code Online (Sandbox Code Playgroud)

并且json API响应具有以下内容:

{
        "Name": "abc",
        "MyEnumValue":"Type1"
}
Run Code Online (Sandbox Code Playgroud)

有时,API会返回MyEnumValue字段的值,该字段未在我的枚举中定义,如下所示:

{
            "Name": "abc",
            "MyEnumValue":"Type4"
    }
Run Code Online (Sandbox Code Playgroud)

这引发了一个例外:

将值"Type4"转换为"MyEnum"类型时出错

有没有办法通过分配默认值或什么来避免应用程序崩溃来处理此错误?

Ili*_*mov 10

Let's say we have the following json string:

[
    {
        "Name": "abc",
        "MyEnumValue": "Type1"
    },
    {
        "Name": "abcd",
        "MyEnumValue": "Type2"
    },
    {
        "Name": "abcde",
        "MyEnumValue": "Type3"
    }    ,
    {
        "Name": "abcdef",
        "MyEnumValue": "Type4"
    }
]
Run Code Online (Sandbox Code Playgroud)

and the following class and enum:

public class MyClass
{
    public string Name { get; set; }

    public MyEnum MyEnumValue { get; set; }
}

public enum MyEnum
{
    Type1,
    Type2,
    Type3
}
Run Code Online (Sandbox Code Playgroud)

As it can be noticed, the json string array contains item (the last one), that cannot be correctly mapped to the MyEnum. To avoid deserialization errors you can use the following code snippet:

static void Main(string[] args)
{         
    var serializationSettings = new JsonSerializerSettings
    {
        Error = HandleDeserializationError
    };

    var lst = JsonConvert.DeserializeObject<List<MyClass>>(jsonStr, serializationSettings);
}

public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
{
    errorArgs.ErrorContext.Handled = true;
    var currentObj = errorArgs.CurrentObject as MyClass;

    if (currentObj == null) return;
    currentObj.MyEnumValue = MyEnum.Type2;            
}
Run Code Online (Sandbox Code Playgroud)

其中jsonStr变量是上面发布的json字符串.在上面的代码示例中,如果MyEnumValue无法正确解释,则将其设置为默认值Type2.

示例:https://dotnetfiddle.net/WKd2Lt

  • 是的,如何为默认值分配解决方案?也许Type5或Type6或TypeX不能等同于Type2?关键是客户端无法预测服务器将来可能会返回什么,因此假设您可以分配默认值是危险的. (2认同)

t3m*_*lar 10

我看到它的唯一方法,你应该编写自己的转换器.但有一半的工作已在课堂上完成StringEnumConverter.我们只能覆盖ReadJson方法

class Program
{
    static void Main(string[] args)
    {
        const string json = @"{
                'Name': 'abc',
                'Type':'Type4'
            }";

        // uncomment this if you want to use default value other then default enum first value
        //var settings = new JsonSerializerSettings();
        //settings.Converters.Add(new FooTypeEnumConverter { DefaultValue = FooType.Type3 });

        //var x = JsonConvert.DeserializeObject<Foo>(json, settings);

        var x = JsonConvert.DeserializeObject<Foo>(json);
    }
}

public class Foo
{
    public string Name { get; set; }

    public FooType Type { get; set; }
}

public enum FooType
{
    Type1,
    Type2,
    Type3
}

public class FooTypeEnumConverter : StringEnumConverter
{
    public FooType DefaultValue { get; set; }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch (JsonSerializationException)
        {
            return DefaultValue;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


dar*_*asd 5

如果您不想创建自定义转换器,另一种方法是将其映射到 DTO 中的私有字符串字段,然后在该字段的属性 getter 中使用 Enum.TryParse:

public class MyClass
{
    [JsonProperty("MyEnumValue")]
    private string myEnumValue;

    public string Name { get; set; }

    [JsonIgnore]
    public MyEnum MyEnumValue 
    { 
        get
        {
            MyEnum outputValue = MyEnum.Default;
            Enum.TryParse(myEnumValue, out outputValue);
            return outputValue;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)