使用Json.Net进行C#枚举反序列化:将值转换为类型时出错
我正在使用Json.NET对一些Json API进行序列化/反序列化 API响应具有一些映射到应用程序中定义的枚举的整数值 枚举如下所示:使用Json.Net进行C#枚举反序列化:将值转换为类型时出错,c#,.net,json,json.net,deserialization,C#,.net,Json,Json.net,Deserialization,我正在使用Json.NET对一些Json API进行序列化/反序列化 API响应具有一些映射到应用程序中定义的枚举的整数值 枚举如下所示: public enum MyEnum { Type1, Type2, Type3 } { "Name": "abc", "MyEnumValue":"Type4" } json API响应具有以下特性: { "Name": "a
public enum MyEnum
{
Type1,
Type2,
Type3
}
{
"Name": "abc",
"MyEnumValue":"Type4"
}
json API响应具有以下特性:
{
"Name": "abc",
"MyEnumValue":"Type1"
}
有时API会为MyEnum中未定义的MyEnumValue字段返回一个值,如下所示:
public enum MyEnum
{
Type1,
Type2,
Type3
}
{
"Name": "abc",
"MyEnumValue":"Type4"
}
这会引发一个异常:
将值“Type4”转换为类型“MyEnum”时出错
有没有办法通过指定默认值或其他方法来处理此错误以避免应用程序崩溃?假设我们有以下json字符串:
[
{
"Name": "abc",
"MyEnumValue": "Type1"
},
{
"Name": "abcd",
"MyEnumValue": "Type2"
},
{
"Name": "abcde",
"MyEnumValue": "Type3"
} ,
{
"Name": "abcdef",
"MyEnumValue": "Type4"
}
]
以及以下类和枚举:
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;
}
static void Main(字符串[]args)
{
var serializationSettings=新的JSONSerializationSettings
{
Error=HandleDeserializationError
};
var lst=JsonConvert.DeserializeObject(jsonStr,serializationSettings);
}
public static void HandleDeserializationError(对象发送方,ErrorEventArgs errorArgs)
{
errorArgs.ErrorContext.Handled=true;
var currentObj=errorArgs.CurrentObject作为MyClass;
if(currentObj==null)返回;
currentObj.MyEnumValue=MyEnum.Type2;
}
其中jsonStr
变量是上面发布的json字符串。在上面的代码示例中,如果无法正确解释MyEnumValue
,则将其设置为默认值Type2
示例:在我看来,您应该编写自己的转换器。但是一半的工作已经在类
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;
}
}
}
类程序
{
静态void Main(字符串[]参数)
{
常量字符串json=@”{
'Name':'abc',
“类型”:“类型4”
}";
//如果要使用默认值而不是默认枚举第一个值,请取消对此的注释
//var settings=new JsonSerializerSettings();
//settings.Converters.Add(新的FooTypeEnumConverter{DefaultValue=FooType.Type3});
//var x=JsonConvert.DeserializeObject(json,设置);
var x=JsonConvert.DeserializeObject(json);
}
}
公开课Foo
{
公共字符串名称{get;set;}
公共FooType类型{get;set;}
}
公共枚举足迹类型
{
类型1,
类型2,
类型3
}
公共类FooTypeEnumConverter:StringEnumConverter
{
public FooType DefaultValue{get;set;}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
尝试
{
return base.ReadJson(reader、objectType、existingValue、serializer);
}
捕获(JsonSerializationException)
{
返回默认值;
}
}
}
如果不想创建自定义转换器,另一种方法是将其映射到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;
}
}
}
您是否尝试过为属性指定
DefaultValue
,谢谢,我尝试过,但仍然有例外ThrownThank,这是一个很好的解决方案Yikes,如何将默认值指定为解决方案?也许Type5、Type6或TypeX不能等同于Type2?关键是客户端无法预测服务器将来可能返回的内容,因此假设您可以指定默认值是危险的。谢谢,这可能是另一种替代解决方案。您是否也可以研究此问题,