2009-06-03 15 views
49

Necesito deserializar algún objeto JavaScript representado en JSON en una clase C# apropiada. Dadas las buenas características de las propiedades automáticas, preferiría tenerlas en estas clases en lugar de solo tener campos. Desafortunadamente, el motor de serialización .NET (al menos, por defecto) ignora por completo las propiedades automáticas en la deserialización y solo se preocupa por el campo de respaldo, que obviamente no está presente en el objeto JavaScript.Deserialización de propiedad automática de C# de JSON

Dado que hay no standard way to name backing fields y para ser honesto, ni siquiera me quiero molestar con el "vamos a crear un objeto JavaScript que se ve como si tuviera campos de respaldo C#", ya que suena un poco sucio, la única manera que pude serialice los campos de JavaScript en C-auto-properties si pudiera forzar al motor de serialización a ignorar de alguna manera el campo de respaldo y usar la propiedad directamente. Lamentablemente, no puedo entender cómo se hace esto o si esto se puede hacer en absoluto. Cualquier idea sería apreciada.

EDITAR: He aquí un ejemplo:

Javascript:

function Cat() 
{ 
    this.Name = "Whiskers"; 
    this.Breed = "Tabby"; 
} 
var cat = new Cat(); 

Ésta es entonces serializado a "{Nombre: 'Bigotes'}".

La clase C#:

[Serializable()] 
public class Cat 
{ 
    public string Name { get; set; } 
    public string Breed { get; set; } 
} 

Y el código de deserialización, que falla:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream); 

Y es evidente a partir de la excepción de que se produce un error porque está buscando para el campo respaldo.

Edit2: Aquí está la excepción, si eso ayuda (sin excepciones internas):

System.Runtime.Serialization.SerializationException

"El tipo de contrato de datos 'Test.Cat' no puede se deserializaron porque requirieron datos miembros '<Name>k__BackingField, <Breed>k__BackingField' no eran encontrado. "

+0

¿Puedes publicar un ejemplo de lo que quieres decir? –

+0

@John Saunders - digamos que obtuve un objeto JavaScript llamado "Cat" con un solo campo llamado "Nombre" con el valor "Bigotes". Digamos que esto está representado en JSON. Quiero tomar este JSON y serializarlo en una instancia de la clase C# Cat (escrita por mí) para que el proceso de serialización llene la propiedad automática "Nombre" de la instancia con "Bigotes". –

+0

... pero el problema es que el serializador está buscando el campo de respaldo (por ejemplo, " k_backingField" pero no necesariamente con este nombre ") y no" Nombre ". –

Respuesta

79

Lo que está sucediendo aquí es que el deserializador está tratando de adivinar el nombre de sus campos de respaldo. Puede resolver esto mediante la adición asignaciones explícitas (atributos DataContract/DataMember) así:

[DataContract] 
public class Cat 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string Breed { get; set; } 
} 
+0

+1 Primera pregunta que respondí, ¡pero no tenía el representante para votar esta respuesta en ese momento! – amelvin

+2

Me gustaría +2 si pudiera. Buscando la respuesta a esto por un momento. – Kelly

+0

super! Me perdí el atributo [DataContract] :( – Ruutert

20

Usted puede hacer esto con JavaScriptSerializer encontrado en el espacio de nombres System.Web.Script.Serialization:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
Cat c = serializer.Deserialize<Cat>(jsonString); 

tengo POCO objetos con propiedades automáticas y esto funciona muy bien.

EDITAR: Escribí sobre JSON Serializers in .NET que compara este serializador con DataContractJsonSerializer.

+0

Sí, parece que voy a estar atascado con el buen viejo JsonExSerializer http://code.google.com/p/ jsonexserializer/ –

1

Supongo que está pasando datos a través de un servicio web. Si está utilizando la clase WebService con el atributo ScriptMethod descompuesto, los métodos del servicio web pueden leer JSON de forma nativa. Incluso usan el mismo JavaScriptSerializer que se mencionó anteriormente. Si está usando WCF, soy un poco más confuso con la lógica.

Pero asegúrese de que su objeto JSON devuelva datos para TODAS las propiedades de su clase. En su error, se menciona una propiedad de Raza que no está en su ejemplo.

También, en el lado de JavaScript, a la naturaleza dinámica de JavaScript es fácil agregar nuevas propiedades a sus objetos. Esto a veces puede conducir a referencias circulares. Debe eliminar los datos adicionales que haya agregado (al igual que está enviando datos a través del método web, y luego volver a agregarlos una vez que haya terminado).

+0

No, desafortunadamente no es un servicio web. Es una simple solicitud ajax que pasa datos en json al servidor. Estoy bastante seguro de que no hay referencias circulares. Tienes razón en que, en el ejemplo, no existe una propiedad de raza, pero en mi código real todas las propiedades están ahí. Gracias por las sugerencias :) –

+0

En el lado de JavaScript de las cosas: ¿cómo está convirtiendo el objeto de JavaScript a JSON? –

+0

@Chris Brandsma: La forma habitual, con json2.js: http://www.json.org/json2.js –

5

baretta's answer resolvió el k__BackingField hincharse para mí. Sólo una pequeña adición que se puede decorar esta clase de auto serializar en XML o JSON de una manera similar:

[Serializable, XmlRoot, DataContract] 
public class Cat 
{ 
    [XmlElement] 
    [DataMember] 
    public string Name { get; set; } 
    [XmlElement] 
    [DataMember] 
    public string Breed { get; set; } 
} 

... y luego usar un DataContractJsonSerializer o XmlSerializer para prepararlo para su punto final.

Cuestiones relacionadas