Serializar diccionario como matriz (de pares de valores clave)

Json.Net normalmente serializa un Dictionary 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 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?

Otra forma de lograr esto es usar un ContractResolver personalizado. De esta manera, no tiene que subclasificar Dictionary 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 .

Ah, resulta que esto es tan sencillo como esperaba. Mi Dictionary 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", } }, ] 

Para este ejemplo, usaré el dictonary:

 var myDict = new Dictionary() { {"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 syntax 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

La solución más simple que encontré es convertir su Dictionary a List> . 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 .

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