2012-01-25 22 views
8

Tengo el siguiente código de muestra C# que se genera automáticamente desde un xsd utilizando la aplicación svcutils.exe.Cómo personalizar la deserialización de una enumeración JSON en .NET?

[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 string Name { get; private set; } 

     [DataMember(Name = "foo")] 
     public Foo Foo { get; private set; } 
    } 

La siguiente es una prueba de la unidad que intenta deserialise un documento de muestra JSON a la clase UNameIt.

[TestClass] 
    public class JsonSerializer_Fixture 
    { 
     public const string 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); 
     } 
    } 

Por desgracia, la prueba falla dando el siguiente motivo:

System.Runtime.Serialization.SerializationException: Se produjo un error deserializar el objeto de tipo MyNamespace.Units.UNameIt. El valor 'Bar' no se puede analizar como el tipo 'Int64'.

La prueba pasará si actualizo mi cadena JSON para reemplazar el especificador de cadena de Enum por un entero, p. Ej.

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

no tengo la flexibilidad para el cambio del suministrado JSON por lo que tiene que encontrar la manera de convertir la representación de cadena Enum quizá en la serialización. Idealmente, me gustaría facilitar esto sin tener que cambiar mi clase de autogenerado porque una vez que vuelva a generar la clase perdería mis cambios.

Me pregunto si sería posible extender el DataContractJsonSerializer a manejos personalizados Enumeraciones? ¿O tal vez hay una mejor manera de hacer esto?

+0

¿Ha intentado eliminar el modificador 'privado' en el método set de la clase UnameIt? Y pruebe su prueba escribiendo "bar" en minúsculas ... –

+0

se recomienda evitar las enumeraciones en los contratos de datos wcf porque crean sutiles problemas compatibles con versiones anteriores. Consulte http://stackoverflow.com/a/788281/52277 –

+0

posible duplicación de [DataContractJsonSerializer y Enums] (http://stackoverflow.com/questions/794838/datacontractjsonserializer-and-enums) – nawfal

Respuesta

6

Este comportamiento es por diseño. He aquí una cita de la Enumerations and JSON paragraph on MSDN: valores de los miembros

de enumeración son tratados como números en JSON, que es diferente de la forma en que son tratados en los contratos de datos, donde son incluidos como nombres de los miembros.

Además, el DataContractJsonSerializer serializará automáticamente todas las enumeraciones, por lo que el EnumMemberAttribute es en realidad ignorada.

Para una solución de , eche un vistazo a this answer on SO.

0

Este es el trabajo:

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

pero no se puede utilizar datamembers atributos, por lo que no se puede cambiar el nombre de propiedades. Debe establecer el nombre de la propiedad como Json enviado.

Cuestiones relacionadas