web-dev-qa-db-fra.com

Json.net sérialiser / désérialiser les types dérivés?

json.net (newtonsoft)
Je regarde la documentation, mais je ne trouve rien sur ce sujet ni sur la meilleure façon de le faire.

public class Base
{
    public string Name;
}
public class Derived : Base
{
    public string Something;
}

JsonConvert.Deserialize<List<Base>>(text);

Maintenant, j'ai des objets dérivés dans la liste sérialisée. Comment désérialiser la liste et récupérer les types dérivés?

83
Will

Si vous stockez le type dans votre text (comme vous devriez l'être dans ce scénario), vous pouvez utiliser le JsonSerializerSettings.

Voir: comment désérialiser JSON dans IEnumerable <BaseType> avec Newtonsoft JSON.NET

Attention, cependant. Utiliser autre chose que TypeNameHandling = TypeNameHandling.None pourrait s’ouvrir jusqu’à ne faille de sécurité .

36
kamranicus

Vous devez activer la gestion du nom de type et la transmettre au (dés) sérialiseur en tant que paramètre de configuration.

Base object1 = new Base() { Name = "Object1" };
Derived object2 = new Derived() { Something = "Some other thing" };
List<Base> inheritanceList = new List<Base>() { object1, object2 };

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
string Serialized = JsonConvert.SerializeObject(inheritanceList, settings);
List<Base> deserializedList = JsonConvert.DeserializeObject<List<Base>>(Serialized, settings);

Cela se traduira par une désérialisation correcte des classes dérivées. L’inconvénient est qu’il nommera tous les objets que vous utilisez, ainsi la liste dans laquelle vous mettez les objets.

88
Madmenyo

Étant donné que la question est si populaire, il peut être utile d’ajouter quoi faire si vous souhaitez contrôler le nom de la propriété de type et sa valeur.

Le long chemin consiste à écrire JsonConverters personnalisé pour gérer la (dé) sérialisation en vérifiant et en définissant manuellement la propriété type.

Un moyen plus simple consiste à utiliser JsonSubTypes , qui manipule tout le socle via des attributs:

[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
    public virtual string Sound { get; }
    public string Color { get; set; }
}

public class Dog : Animal
{
    public override string Sound { get; } = "Bark";
    public string Breed { get; set; }
}

public class Cat : Animal
{
    public override string Sound { get; } = "Meow";
    public bool Declawed { get; set; }
}
12
rzippo