I'm trying to figure out how to deserialize a JSON string into an enum. Right now I'm taking a serialized Dictionary, passing it to an HttpPut method, and deserializing that string in order to update fields on a custom object using reflection. Here's what I have so far:
I'm putting values into the Dictionary like this:
Dictionary<string, object> valuesToUpdate = new Dictionary<string, object>();
valuesToUpdate.Add("Length", 64.0); //Length is a double
valuesToUpdate.Add("Confidence", SimpleConfidence.THREE); //Confidence is an enum
I'm using JSON to serialize is like this:
string jsonString = JsonConvert.SerializeObject(valuesToUpdate);
I then take the jsonString and send it over to a REST API PUT call. My goal with this is to update various variables for a custom object based on the Key values in the dictionary using reflection (in this example I'll be updating customObject.Confidence and customObject.Length).
The PUT call deserializes the jsonString like this:
Dictionary<string, object> newFields = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
My plan is to iterate through newFields and use reflection to update customObject's fields. Right now I have some code that works when the dictionary finds strings or doubles but I'm having issues with other types - mainly enums and classes. So basically, how would one go about taking a serialized json dictionary string, deserialize it into the appropriate type for reflection? With the example I've posted, "Length" will update properly, but "Confidence" will throw this error:
Object of type 'System.Int64' cannot be converted to type 'System.Nullable'1.
This is my HttpPut method that reads the jsonString:
[HttpPut("/test/stuff")]
public string PutContact([FromBody]dynamic jsonString)
{
Dictionary<string, object> newFields = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
foreach(var field in newFields)
{
Console.WriteLine("\nField key: " + field.Key);
Console.WriteLine("Field value: " + field.Value + "\n");
PropertyInfo propInfo = typeof(CustomObject).GetProperty(field.Key);
var value = propInfo.GetValue(customObject, null);
propInfo.SetValue(customObject, field.Value, null);
}
}
So it seems likes it's deserializing the original enum into type Int64. How would I go about getting it to recognize it as the original type of SimpleConfidence which is an enum?
The type identity of the enum SimpleConfidence
is lost between the serialization and deserialization. You can patch it around by adding some special handling on the assignment part :
//...
foreach(var field in newFields)
{
// ...
PropertyInfo propInfo = typeof(CustomObject).GetProperty(field.Key);
var value = propInfo.GetValue(customObject, null);
PropertyInfo propInfo = null;
// handles TEnum
if (propInfo.PropertyType.IsEnum)
{
propInfo.SetValue(customObject, Enum.ToObject(propInfo.PropertyType, field.Value), null);
}
// handles TEnum?
else if (Nullable.GetUnderlyingType(propInfo.PropertyType)?.IsEnum == true)
// if previous line dont compile, use the next 2
//else if (Nullable.GetUnderlyingType(propInfo.PropertyType) != null &&
// Nullable.GetUnderlyingType(propInfo.PropertyType).IsEnum)
{
propInfo.SetValue(customObject, Enum.ToObject(Nullable.GetUnderlyingType(propInfo.PropertyType), field.Value), null);
}
else
{
propInfo.SetValue(customObject, field.Value, null);
}
}