Comment personnaliser la désérialisation d’une énumération JSON dans .NET?

J’ai l’exemple de code C # suivant généré automatiquement à partir d’un xsd à l’aide de l’application svcutils.exe.

[DataContract] public enum Foo { [EnumMember(Value = "bar")] Bar = 1, [EnumMember(Value = "baz")] Baz = 2 } [DataContract] public class UNameIt { [DataMember(Name = "id")] public long Id { get; private set; } [DataMember(Name = "name")] public ssortingng Name { get; private set; } [DataMember(Name = "foo")] public Foo Foo { get; private set; } } 

Voici un test unitaire qui tente de désérialiser un exemple de document JSON dans la classe UNameIt.

  [TestClass] public class JsonSerializer_Fixture { public const ssortingng JsonData = @"{ ""id"":123456, ""name"":""John Doe"", ""foo"":""Bar""}"; [TestMethod] public void DataObjectSimpleParseTest() { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(UNameIt)); MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(JsonData)); UNameIt dataObject = serializer.ReadObject(ms) as UNameIt; Assert.IsNotNull(dataObject); Assert.AreEqual(123456, dataObject.Id); Assert.AreEqual(Foo.Baz, dataObject.Foo); } } 

Malheureusement, le test échoue en donnant la raison suivante:

System.Runtime.Serialization.SerializationException: une erreur s’est produite lors de la désérialisation de l’object de type MyNamespace.Units.UNameIt. La valeur “Bar” ne peut pas être analysée sous le type “Int64”.

Le test réussira si je mets à jour ma chaîne JSON afin de remplacer le spécificateur de chaîne pour Enum par un entier, par exemple

 public const ssortingng JsonData = @"{ ""id"":123456, ""name"":""John Doe"", ""foo"":""1""}"; 

Je n’ai pas la possibilité de changer le JSON fourni, je dois donc comprendre comment convertir la représentation Enum de chaîne, peut-être lors de la sérialisation. Idéalement, j’aimerais faciliter cela sans avoir à changer de classe à génération automatique, car une fois que je générerais à nouveau la classe, je perdrais mes modifications.

Je me demande s’il serait possible d’étendre DataContractJsonSerializer au traitement personnalisé des énumérations? Ou peut-être qu’il y a un meilleur moyen de faire ça?

Ce comportement est voulu . Voici une citation du paragraphe Enumerations et JSON sur MSDN :

Les valeurs de membre d’énumération sont traitées comme des nombres dans JSON, ce qui diffère de la façon dont elles sont traitées dans les contrats de données, où elles sont incluses en tant que noms de membre.

De plus, DataContractJsonSerializer sérialisera automatiquement toutes les énumérations, de sorte que EnumMemberAtsortingbute est en réalité ignoré.

Pour une solution de contournement , jetez un oeil à cette réponse sur SO .

C’est du travail:

 var ret = new JavaScriptSerializer().Deserialize(retApi.Item2); 

Mais vous ne pouvez pas utiliser d’atsortingbuts datamembers et ne pouvez donc pas renommer les propriétés Vous devez définir le nom de la propriété comme Json envoyé.