Десериализовать строку 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. Моя цель состоит в том, чтобы обновить различные переменные для пользовательского объекта на основе значений Key в словаре, используя отражение (в этом примере я буду обновлять 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, который является перечислением?
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);
}
}