0

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?

Roka545
  • 3,404
  • 20
  • 62
  • 106

1 Answers1

0

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

}
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44
  • Would you happen to know how to deserialize a JSON string into a class as well? I created a separate post for it here: http://stackoverflow.com/questions/36728307/deserialize-json-string-into-class-with-reflection – Roka545 Apr 19 '16 at 20:02