J'utilise DataContractJsonSerializer
pour désérialiser des objets d'un service externe. Dans la plupart des cas, cela a très bien fonctionné pour moi. Cependant, il y a un cas où je dois désérialiser JSON qui contient une liste d'objets qui héritent tous de la même classe de base, mais il y a beaucoup de différents types d'objets dans cette liste.Désérialisation d'une liste mixte d'objets à partir de JSON
Je sais que cela peut être fait facilement en incluant une liste de types connus dans le constructeur du sérialiseur, mais je n'ai pas accès au code qui a généré ce service JSON. Les types que j'utilise seront différents des types utilisés dans le service (surtout le nom de classe et l'espace de noms seront différents). En d'autres termes, les classes avec lesquelles les données ont été sérialisées ne seront pas les mêmes que celles que j'utiliserai pour les désérialiser, même si elles seront très similaires.
Avec le XML DataContractSerializer
, je peux passer un DataContractResolver
pour mapper les types de services à mes propres types, mais il n'y a pas un tel constructeur pour le DataContractJsonSerializer
. Y a-t-il un moyen de le faire? Les seules options que j'ai pu trouver sont: écrire mon propre désérialiseur, ou utiliser Microsoft's JsonObject qui n'a pas été testé et "ne devrait pas être utilisé dans des environnements de production".
Voici un exemple:
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
}
[DataContract]
public class Student : Person
{
[DataMember]
public int StudentId { get; set; }
}
class Program
{
static void Main(string[] args)
{
var jsonStr = "[{\"__type\":\"Student:#UnknownProject\",\"Name\":\"John Smith\",\"StudentId\":1},{\"Name\":\"James Adams\"}]";
using (var stream = new MemoryStream())
{
var writer = new StreamWriter(stream);
writer.Write(jsonStr);
writer.Flush();
stream.Position = 0;
var s = new DataContractJsonSerializer(typeof(List<Person>), new Type[] { typeof(Student), typeof(Person) });
// Crashes on this line with the error below
var personList = (List<Person>)s.ReadObject(stream);
}
}
}
Voici l'erreur mentionnée dans le commentaire ci-dessus:
Element ':item' contains data from a type that maps to the name
'http://schemas.datacontract.org/2004/07/UnknownProject:Student'. The
deserializer has no knowledge of any type that maps to this name. Consider using
a DataContractResolver or add the type corresponding to 'Student' to the list of
known types - for example, by using the KnownTypeAttribute attribute or by adding
it to the list of known types passed to DataContractSerializer.