c# json.net

c# - Serializar diccionario como matriz(de pares de valores clave)



json.net (5)

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", } }, ]

Json.Net normalmente serializa un Dictionary<k,v> en una colección;

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

Lo cual es genial. 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 Array;

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

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


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() } )


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


Otra forma de lograr esto es usar un ContractResolver personalizado. De esta manera, no tiene que subclasificar 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 se serialicen como una matriz de objetos con propiedades "Clave" y "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 usar la resolución, agréguela a su JsonSerializerSettings , luego pase la configuración a JsonConvert.SerializeObject() esta manera:

JsonSerializerSettings settings = new JsonSerializerSettings(); settings.ContractResolver = new DictionaryAsArrayResolver(); string json = JsonConvert.SerializeObject(obj, settings);

Aquí hay una demostración funcional .


Para este ejemplo, usaré el dictonary:

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

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

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

Podría hacer una transformación usando LINQ para crear un objeto anónimo y serializar eso:

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

O podrías usar un objeto real

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

y la sintaxis LINQ anterior o la alternativa:

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

De cualquier manera, esto se serializa a:

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

.NET Fiddle link: https://dotnetfiddle.net/LhisVW