2010-01-22 15 views
20

Estoy intentando consumir un servicio web RESTful usando WCF. No tengo control sobre el formato del servicio web, así que tengo que hacer algunas soluciones aquí y allá. Sin embargo, uno de los principales problemas que no logro resolver es cómo hacer que WCF deserialice una enumeración como una cadena.wcf deserialize enum como cadena

Este es mi código (nombres cambiados, obviamente):

[DataContract] 
public enum Foo 
{ 
    [EnumMember(Value = "bar")] 
    Bar, 

    [EnumMember(Value = "baz")] 
    Baz 
} 

[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; } 
} 

Y estos son los datos devueltos que se produce un error de deserialización:

{ 
    "id":123456, 
    "name":"John Doe", 
    "foo":"bar" 
} 

Por último, la excepción lanzada:

Hubo un error al deserializar el objeto de tipo Service.Foo. El valor 'bar' no se puede analizar como el tipo 'Int64'.

No quiero cambiar al uso de XmlSerializer, porque, entre sus muchas otras deficiencias, no me dejará establecer entidades privadas en las propiedades.

¿Cómo puedo hacer que WCF (o, bueno, el DataContractSerializer) trate mi enumeración como valores de cadena?

EDIT: Hacer esto parece ser imposible, y el comportamiento es la forma en que es por diseño. Gracias Microsoft, por no darnos opciones, tener que recurrir a hacks. Hacerlo de la manera que sugiere somori parece ser la única forma de obtener enumeraciones de cadenas con JSON y WCF.

+0

¿Ha intentado crear un objeto UnameIt en código y usar el DataContractSerializer para serializarlo (y luego deserializarlo) para ver si tal vez la serialización no coincide con el mensaje que recibe? – GaussZ

+0

La cuestión es que yo no soy el que está haciendo la serialización. Este JSON proviene de un tercero. No puedo controlar nada al respecto, lo único que tengo control es la deserialización, excepto que supongo que no, porque no puedo lograr que WCF deserialice una enumeración de la forma en que estos tipos establecen enums. Ojalá DataContractSerializer fuera más flexible. – Alex

+0

Sí entiendo que usted no tiene ningún control sobre él, sería tal vez insinuar el problema, aunque si se podría comparar un objeto auto-serializado con lo que se obtiene a partir del tercero para entender por qué el serializador no le gusta. – GaussZ

Respuesta

7

Esto podría ser una pregunta tonta.

¿Qué pasa si lo hace

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

public Foo Foo 
{ 
    get 
    { 
    return Foo.Parse(foo); 
    } 
} 

?

+3

Ya lo he intentado, y eso funciona, pero es un truco, y si se puede evitar, quiero evitarlo. – Alex

+1

En realidad, esta parece ser la única manera de hacerlo, ver http://stackoverflow.com/questions/794838/datacontractjsonserializer-and-enums/794962#794962 – Alex

+0

Se necesitaría un regulador también, ¿verdad? –

0

Er ..? ¿Las enum no son enteros? La excepción es válida No sé si esto ayuda: http://msdn.microsoft.com/en-us/library/aa347875.aspx

+0

No, no lo es. ¿Has leído ese artículo tú mismo? He aquí un extracto interesante: En general, el contrato de datos incluye nombres de los miembros de enumeración, no valores numéricos. Sin embargo, cuando se utiliza el modelo de contrato de datos, si el lado receptor es un cliente WCF, el esquema exportado conserva los valores numéricos. El problema es, que estoy siendo un cliente WCF. Sin embargo, el servidor usa enumeraciones de cadenas. Estoy un poco perplejo ... – Alex

+0

¿Podría el código del servidor tener errores? ¿Es posible usar la estructura de datos en esta instancia? –

+0

El servidor no es un servicio WCF, creo que ejecuta Python. No puedo cambiar la forma en que hacen las cosas, solo soy un consumidor en este escenario, y tengo que seguir sus reglas. – Alex

1

Sé que esta es una publicación anterior, pero creo que vale la pena mencionarla.

Recibí un error similar donde falló la deserialización de la cadena json, pareciendo deserializar a los tipos incorrectos.

La solución para mí fue simplemente URL codificar la cadena json antes de enviarla al servidor. Un error simple pero fácil de hacer.

HttpUtility.UrlEncode(JSONInstruction) /*remember to encode the string*/ 
0

Esto tal vez está sucediendo porque el colocador es privado y el error informado es engañoso. El Foo es la primera propiedad en ser deserializada y dado que no hay un organismo público disponible, arroja una excepción.