Десериализовать строку JSON в перечисление

Я пытаюсь понять, как десериализовать строку JSON в перечисление. Прямо сейчас я беру сериализованный словарь, передаю его методу HttpPut и десериализую эту строку, чтобы обновлять поля пользовательского объекта с помощью отражения. Вот что у меня есть до сих пор:

Я помещаю значения в словарь следующим образом:

  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

Я использую JSON для сериализации, как это:

string jsonString = JsonConvert.SerializeObject(valuesToUpdate);

Затем я беру jsonString и отправляю его на вызов REST API PUT. Моя цель — обновить различные переменные для пользовательского объекта на основе значений ключа в словаре с использованием отражения (в этом примере я буду обновлять customObject.Confidence и customObject.Length).

Вызов PUT десериализует jsonString следующим образом:

Dictionary<string, object> newFields = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);

Мой план состоит в том, чтобы перебирать newFields и использовать отражение для обновления полей customObject. Прямо сейчас у меня есть код, который работает, когда словарь находит строки или двойные числа, но у меня проблемы с другими типами — в основном с перечислениями и классами. Итак, как можно взять сериализованную строку словаря json, десериализовать ее в соответствующий тип для отражения? В примере, который я опубликовал, «Длина» будет обновляться правильно, но «Уверенность» выдаст эту ошибку:

Object of type 'System.Int64' cannot be converted to type 'System.Nullable'1.

Это мой метод HttpPut, который читает 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);
        }
}

Так что похоже, что он десериализует исходное перечисление в тип Int64. Как мне заставить его распознать его как исходный тип SimpleConfidence, который является перечислением?


person Roka545    schedule 18.04.2016    source источник


Ответы (1)


Идентификация типа перечисления SimpleConfidence теряется между сериализацией и десериализацией. Вы можете исправить это, добавив специальную обработку части присваивания:

//...

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

}
person Xiaoy312    schedule 18.04.2016
comment
Вы случайно не знаете, как десериализовать строку JSON в класс? Я создал для этого отдельный пост здесь: stackoverflow.com/questions/36728307/ - person Roka545; 19.04.2016