2012-10-05 16 views
25

Json.Net suele serializar un Dictionary<k,v> en una colección;Json.Net - Diccionario de serialización como matriz (de pares de valores clave)

"MyDict": { 
    "Apples": { 
    "Taste": 1341181398, 
    "Title": "Granny Smith", 
    }, 
    "Oranges": { 
    "Taste": 9999999999, 
    "Title": "Coxes Pippin", 
    }, 
} 

Cuál es grande. Y al mirar alrededor de SO, parece ser lo que la mayoría de la gente quiere. Sin embargo, en este caso particular, quiero serializar entre mi Dictionary<k,v> y el formato de matriz;

"MyDict": [ 
    "k": "Apples", 
    "v": { 
     "Taste": 1341181398, 
     "Title": "Granny Smith", 
    } 
    }, 
    "k:": "Oranges", 
    "v:": { 
     "Taste": 9999999999, 
     "Title": "Coxes Pippin", 
    } 
    }, 
] 

¿Hay alguna manera fácil de hacerlo con mi tipo de campo existente? ¿Hay algún atributo que pueda anotar, por ejemplo?

Respuesta

21

Ah, resulta que esto es tan sencillo como esperaba. Mi Dictionary<k,v> ya está subclasificado y descubrí que puedo anotarlo con [JsonArrayAttribute]. Eso me da exactamente el formato que necesito;

"MyDict": [ 
    { 
    "Key": "Apples", 
    "Value": { 
     "Taste": 1341181398, 
     "Title": "Granny Smith", 
    } 
    }, 
    { 
    "Key:": "Oranges", 
    "Value:": { 
     "Taste": 9999999999, 
     "Title": "Coxes Pippin", 
    } 
    }, 
] 
11

Para este ejemplo, voy a utilizar el Dictonary:

var myDict = new Dictionary<string,string>() { 
    {"a","123"}, 
    {"b","234"}, 
    {"c","345"} 
}; 

la que serializa (con Newtonsoft.Json.JsonConvert.SerializeObject(myDict)) a:

{"a":"123","b":"234","c":"345"} 

que podría hacer una transformación usando LINQ para crear una objeto anónimo, y serializar eso:

var myDictTransformed = from key in myDict.Keys 
         select new { k = key, v = myDict[key] }; 

O usted podría utilizar un objeto real

class MyDictEntry 
{ 
    public string k { get; set; } 
    public string v { get; set; } 
} 

y, o bien lo anterior o la sintaxis de LINQ alternativa:

var myDictTransformed = myDict.Keys.AsEnumerable() 
         .Select(key => new MyDictEntry{ 
          k = key, 
          v = myDict[key] 
         }); 

De cualquier manera, este serializa a:

[ 
    {"k":"a", "v":"123"}, 
    {"k":"b", "v":"234"}, 
    {"k":"c", "v":"345"} 
] 

.NET violín: https://dotnetfiddle.net/LhisVW

1

La respuesta de gregmac fue útil, pero no funcionó del todo. La siguiente es la misma idea ... sin los juegos de palabras.

var dictionaryTransformed = dictionary.Select(item => item.Key).Select(i => 
         new {Key = i, Value = dictionary[i] }); 

o, por supuesto

var dictionaryTransformed = dictionary.Select(item => 
         new {item.Key, Value = dictionary[item.Key] }); 

Entonces a JSON

var json = (new JavaScriptSerializer()).Serialize( 
         new { Container = dictionaryTransformed.ToArray() }) 
27

Otra forma de lograr esto es utilizar una costumbre ContractResolver. De esta forma, no es necesario crear la subclase Dictionary<K,V> ni aplicar una transformación cada vez que serializa, como se sugiere en otras respuestas.

La siguiente resolución hará que todos los diccionarios a ser serializados como un conjunto de objetos con "Key" y propiedades "Valor":

class DictionaryAsArrayResolver : DefaultContractResolver 
{ 
    protected override JsonContract CreateContract(Type objectType) 
    { 
     if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) || 
      (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>)))) 
     { 
      return base.CreateArrayContract(objectType); 
     } 

     return base.CreateContract(objectType); 
    } 
} 

Para utilizar el dispositivo de resolución, añadirlo a su JsonSerializerSettings, a continuación, pasar el ajustes a JsonConvert.SerializeObject() como esto:

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.ContractResolver = new DictionaryAsArrayResolver(); 

string json = JsonConvert.SerializeObject(obj, settings); 

que aquí hay una working demo.

+0

Trabajando para la serialización, ahora Cómo deserializar el mismo objeto – MSTdev

+0

@MSTdev La misma idea, use 'JsonConvert.DeserializeObject' y asegúrese de pasar el' JsonSerializerSettings' con la resolución a ese método. Actualicé el violín para demostrar. –

+0

@BrianRogers compruebe mi problema detallado http://stackoverflow.com/questions/32473308/serialize-deserialization-issue-on-newton-json-for-idictionarymycustomclass-li – MSTdev

7

La solución más simple que encontré es convertir su Dictionary<string, string> en . JSON.NET luego convierte su List en una matriz de objetos con el formato { Key: 'keyname', Value: 'value' }. Esto funciona bien si acepta el cambio de modelo requerido y no desea subclasificar su Dictionary.

+0

El uso de los métodos de extensión ToList() o ToArray() hace que esto fácil. –

Cuestiones relacionadas