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

本文关键字:转换 错误 类型 Net Json 枚举 反序列化 使用 | 更新日期: 2023-09-27 18:05:07

我使用Json。. NET来序列化/反序列化一些JSON api。

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

枚举如下:

public enum MyEnum
{
    Type1,
    Type2,
    Type3
}

和JSON API响应有以下内容:

{
    "Name": "abc",
    "MyEnumValue":"Type1"
}

有时API会返回MyEnumValue字段的值,而这个值没有在我的enum中定义,就像这样:

{
    "Name": "abc",
    "MyEnumValue":"Type4"
}

抛出异常:

转换值"type4"错误;输入'MyEnum'

是否有一种方法来处理这个错误,通过分配一个默认值或其他东西,以避免应用程序崩溃?

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

在我看来,您应该编写自己的转换器。但是在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;
        }
    }
}

假设我们有以下json字符串:

[
    {
        "Name": "abc",
        "MyEnumValue": "Type1"
    },
    {
        "Name": "abcd",
        "MyEnumValue": "Type2"
    },
    {
        "Name": "abcde",
        "MyEnumValue": "Type3"
    }    ,
    {
        "Name": "abcdef",
        "MyEnumValue": "Type4"
    }
]

和下面的类和enum:

public class MyClass
{
    public string Name { get; set; }
    public MyEnum MyEnumValue { get; set; }
}
public enum MyEnum
{
    Type1,
    Type2,
    Type3
}

可以注意到,json字符串数组中包含不能正确映射到MyEnum的项目(最后一个)。要避免反序列化错误,可以使用以下代码片段:

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;            
}

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

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

如果您不想创建自定义转换器,则可以选择将其映射到DTO中的私有字符串字段,然后使用Enum。在该字段的属性getter中尝试解析:

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;
        }
    }
}