C# Enum deserialization with Json.Net: Error converting value to type
Solution 1
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"
}
]
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
}
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;
}
where the jsonStr
variable is the posted json string above. In the above code sample, if MyEnumValue
cannot be correctly interpreted, it is set to a default value of Type2
.
Example: https://dotnetfiddle.net/WKd2Lt
Solution 2
The only way I see it, you should write your own converter. But half of work is already done in class StringEnumConverter
. We can override only ReadJson
method
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;
}
}
}
Solution 3
An alternative, if you don't want to create a custom converter, is to map it to a private string field in your DTO and then use Enum.TryParse in that field's property 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;
}
}
}
Related videos on Youtube
Mina Wissa
Developer with experience in developing mobile applications for Android, iOS and Windows with native SDKs and cross platform frameworks. www.linkedin.com/in/mina-wissa
Updated on June 06, 2022Comments
-
Mina Wissa almost 2 years
I'm using Json.NET to serialize/deserialize some JSON APIs.
The API response have some integer values that map to an Enum defined in the application.
The enum is like this:
public enum MyEnum { Type1, Type2, Type3 }
and the JSON API response has the following:
{ "Name": "abc", "MyEnumValue":"Type1" }
sometimes the API returns a value for the MyEnumValue field that's not defined in my enum, like this:
{ "Name": "abc", "MyEnumValue":"Type4" }
That throws an exception:
Error converting value "Type4" to type 'MyEnum'
Is there a way to handle this error by assigning a default value or something to avoid the application crash?
-
3dd almost 9 yearsHave you tried specifying the
DefaultValue
for the property newtonsoft.com/json/help/html/… -
Mina Wissa almost 9 yearsThanks, I tried but still the exception is thrown
-
-
Mina Wissa almost 9 yearsThanks, this is a nice solution
-
Mina Wissa almost 9 yearsThanks, that can be another alternative solution
-
Mike Taverne about 8 yearsYikes, how is assigning a default value a solution? Maybe Type5 or Type6 or TypeX cannot be equated to Type2? The point is the client cannot anticipate what the server might return in future, so assuming you can assign a default value is dangerous.
-
Nikunj Patel almost 4 yearsCan you also look into this problem, json with Enum DisplayName or EnumMember Value