Newtonsoftは、継承オブジェクトまたはサブクラスオブジェクトのリストを適切に逆シリアル化できますか?[複製]

Dec 08 2020

Newtonsoft(with TypeNameHandling.All)を使用しList<Animal>て、a<Cat>とaを含むa<Dog>をシリアル化すると、文字列をに逆シリアル化すると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リストは次のようになります(犬と猫のタイプに注意してください)。

これで、シリアル化されると、サブクラスが正しく含まれていることがわかります。同様のオブジェクトに逆シリアル化するのに十分な情報である必要があります。

{
    "$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"
            }
        ]
    }
}

しかし、逆シリアル化されると、DogCatはなくなります。彼らはちょうど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);
}

印刷する必要があります:犬猫