Как я могу использовать Newtonsoft для десериализации JSON в различные типы с пользовательскими значениями в словаре? - PullRequest
0 голосов
/ 12 марта 2020

У меня есть несколько интересных JSON для десериализации:

[
   {
      "animal": "cat",
      "age": 3,
      "fields": { "catName": "Fluffy" }
   },
   {
      "animal": "dog",
      "age": 4,
      "fields": { "dogName": "Fido" }
   }
]

и, конечно, я бы хотел, чтобы он был десериализован в красивые объекты:

public class Animal
{
   public int age {get; set; }
}
public class Cat : Animal
{
   public string catName {get; set; }
}
public class Dog : Animal
{
   public string dogName {get; set; }
}

Animal[] animals = JsonConvert.DeserializeObject<Animal[]>(jsonText, new AnimalConverter());

На основе кода в этот ответ , я могу генерировать объекты "Cat" и "Dog" надлежащим образом, но теперь я не уверен, как извлечь информацию из словарей "fields". Как я могу это сделать?

Я знаю, что могу добавить члена "fields" в Animal:

public class Animal
{
   public int age {get; set; }
   public Dictionary<string, string> fields {get; set; }
}

, а затем добавить код для Cat и Dog, чтобы извлечь поля в отдельные свойства. , но похоже, что должен быть более простой способ!

public class Cat
{
   public string catName {get; set; }

   public void AfterDeserialization()
   {
      catName = fields["catName"];
   }
}

РЕДАКТИРОВАТЬ

На основе этого ответа (который я нашел после публикации моего вопроса), я добавил код как это:

public void SetFields(JProperty fields)
{
   if ((fields != null) && (fields.Value is JObject objectValue))
   {
      foreach (JProperty jsonProp in objectValue.Properties())
      {
         var propInfo = GetType().GetProperty(jsonProp.Name);
         if (propInfo != null)
         {
             var value = jsonProp.ToObject(propInfo.PropertyType);
             propInfo.SetValue(this, value);
         }
         else
             Debug.WriteLine("*** Missing property \"" + jsonProp.Name + "\" on " + GetType().Name);
      }
   }
}

и в моем собственном конвертере, после того как я создаю каждый объект типа Cat или Dog (в зависимости от атрибута "animal"), я тогда делаю это:

JProperty fields = item.Property("fields");
if (fields != null)
   animal.SetFields(fields);

Это самый простой / лучший способ сделать это?

ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ

Десериализация не установила свойство age в моем базовом классе. Я попробовал кучу предложений из разных ответов stackoverflow, но ни один из них не сработал. В итоге я вручную установил свойства базового класса.

...