Может ли Newtonsoft правильно десериализовать список унаследованных объектов или объектов подкласса? [дубликат]

Dec 08 2020

Используя Newtonsoft (with TypeNameHandling.All), если я сериализую a, List<Animal>который включает a <Cat>и a <Dog>, когда я десериализую строку обратно в a List<Animal>, они теряют свое наследование и становятся справедливыми <Animals>.

Есть ли у Newtonsoft способ сохранить подклассы, когда они десериализованы обратно в Listродительский класс?

Вот объекты:

 public class Zoo
    {
        public List<Animal> Animals;

        public Zoo()
        {
            Animals = new List<Animal>();
        }
    }
    public class Animal
    {

    }

    public class Dog : Animal
    {

    }

    public class Cat : Animal
    {

    }
}

Вот тест:

static void Main(string[] args)
        {
            var zoo = new Zoo();
            var dog = new Dog();
            var cat = new Cat();
            zoo.Animals.Add(dog);
            zoo.Animals.Add(cat);

            var json = JsonConvert.SerializeObject(zoo, Formatting.None,
                new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.All
                });

            var newZoo = JsonConvert.DeserializeObject<Zoo>(json);
        }

Вот как выглядит исходный список Zoo.Animal (обратите внимание на типы Dog и Cat):

Теперь, когда он сериализован, мы видим, что подклассы включены правильно. Должно быть достаточно информации, чтобы десериализовать его обратно в аналогичный объект:

{
    "$type": "Sample.Sandbox.Zoo, Sample.Sandbox", "Animals": { "$type": "System.Collections.Generic.List`1[[Sample.Sandbox.Animal, Sample.Sandbox]], System.Private.CoreLib",
        "$values": [ { "$type": "Sample.Sandbox.Dog, Sample.Sandbox"
            },
            {
                "$type": "Sample.Sandbox.Cat, Sample.Sandbox"
            }
        ]
    }
}

Но когда он десериализуется, символы Dogи Catисчезают. Они только что Animals:

Есть ли способ для Newtonsoft правильно десериализовать JSON и поддерживать типы подклассов?

Большое спасибо за любые советы.

Ответы

1 Richard Dec 08 2020 at 12:10

Вам нужно добавить настройки как для сериализатора, так и для десериализатора.

попробуй это:

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
var json = JsonConvert.SerializeObject(zoo,settings);    
var newZoo = JsonConvert.DeserializeObject<Zoo>(json,settings);
    
foreach (var currentAnimal in newZoo.Animals)
{ 
   Console.WriteLine(currentAnimal.GetType().Name);
}

Следует распечатать: Собака Кошка