2009-02-27 15 views
22

Tengo el siguiente fragmento de JSON:problema Deserialización con DataContractJsonSerializer

[{ 
    "name": "numToRetrieve", 
    "value": "3", 
    "label": "Number of items to retrieve:", 
    "items": { 
     "1": "1", 
     "3": "3", 
     "5": "5" 
    }, 
    "rules": { 
     "range": "1-2" 
    } 
}, 
{ 
    "name": "showFoo", 
    "value": "on", 
    "label": "Show foo?" 
}, 
{ 
    "name": "title", 
    "value": "Foo", 
    "label": "Foo:" 
}] 

Todo en una versión de línea (apto para una cadena literal):

[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}] 

En el ejemplo anterior, name , value y label son obligatorios pero items y rules son opcionales.

Aquí está la clase que estoy tratando de deserializar en:

using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 

namespace foofoo 
{ 
    [DataContract] 
    public sealed class FooDef 
    { 
     [DataMember(Name = "name", IsRequired = true)] 
     public string Name { get; set; } 

     [DataMember(Name = "value", IsRequired = true)] 
     public string Value { get; set; } 

     [DataMember(Name = "label", IsRequired = true)] 
     public string Label { get; set; } 

     [DataMember(Name = "items", IsRequired = false)] 
     public Dictionary<string, string> Items { get; set; } 

     [DataMember(Name = "rules", IsRequired = false)] 
     public Dictionary<string, string> Rules { get; set; } 
    } 
} 

Aquí está el código que utilizo para deserializar:

var json = new DataContractJsonSerializer(typeof(List<FooDef>)); 
var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]"; 
var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar)); 
var foo = json.ReadObject(stream); 
stream.Close(); 

Todo va razonablemente bien excepto que items y rules están vacíos para el primer pase FooDef. He intentado todo bajo el sol para tratar de que se llenen: clases personalizadas, NameValueCollection, KeyValuePair<string, string>, List tanto de esta última como de cualquier otra colección que parezca aplicarse. [EDIT: me olvidé de probar Hashtable, que parecía ser un candidato obvio. No funcionó.]

El problema, como yo lo veo, es que la pieza clave bajo items y rules es abierta. Es decir, no siempre se llamará range o 3. ¿Algún consejo o idea?

Respuesta

21

En mi humilde opinión no hay forma de deserializar la cadena JSON que proporcionó en una clase .NET utilizando DataContractJsonSerializer.

El problema proviene del modo en que DataContractJsonSerializer serializa los diccionarios. Puede usar un serializador alternativo como Json.NET (que recomiendo encarecidamente) o JavaScriptSerializer (creo que ya no está en uso de DataContractJsonSerializer, pero funcionará para su escenario).

También puede leer theserants.

Documentación: Serializing Collections - Json.NET

+0

Eso es lo que temía. Estaba evitando cambiar a JavaScriptSerializer debido a la desaprobación, pero me alegra saber que no fue detectado en 3.5 SP1. Lo intentaré usando esa clase. – bbrown

+1

Lo probé con JavaScriptSerializer y funcionó perfectamente. Terminé usando Dictionary pero Hashtable también funcionó. – bbrown

+2

+1 para Json.NET –

Cuestiones relacionadas