¿Cómo convierto un diccionario a una cadena JSON en C #?

130

Quiero convertir mi Dictionary<int,List<int>>cadena a JSON. ¿Alguien sabe cómo lograr esto en C #?

daehaai
fuente
3
Use el paquete nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Respuestas:

118

Serializar estructuras de datos que contienen solo valores numéricos o booleanos es bastante sencillo. Si no tiene mucho para serializar, puede escribir un método para su tipo específico.

Para Dictionary<int, List<int>>lo que ha especificado, puede usar Linq:

string MyDictionaryToJson(Dictionary<int, List<int>> dict)
{
    var entries = dict.Select(d =>
        string.Format("\"{0}\": [{1}]", d.Key, string.Join(",", d.Value)));
    return "{" + string.Join(",", entries) + "}";
}

Pero, si está serializando varias clases diferentes, o estructuras de datos más complejas, o especialmente si sus datos contienen valores de cadena , sería mejor usar una biblioteca JSON confiable que ya sepa cómo manejar cosas como caracteres de escape y saltos de línea. Json.NET es una opción popular.

gilly3
fuente
66
Esta solución es ingenua en el mejor de los casos. Utilice una biblioteca de serialización json real.
jacobsimeon
131
@Jacob - ¿Ingenuo? Ay. Personalmente, no puedo justificar incluir otro ensamblaje cuando todo lo que necesito hacer se puede lograr con un método corto y simple.
gilly3
16
Un comentario más sobre gilly3. En algún momento estás codificando en Windows Phone. Estás agregando zlip, twitter, google, cosas de procesamiento de audio, cosas de procesamiento de imágenes. Es mejor implementar un método simple como este, y algunas HttpRequests básicas para la interacción en las redes sociales si su uso es simple. Al agregar un ensamblaje, siempre tiene que lidiar con errores y con la imposibilidad de obtener una versión lite. Por cierto, dentro de json libs, hay métodos ingenuos como este y no hay magia.
Léon Pelletier
14
Debería haber una página en cada proyecto abierto que le diga: "Oye, la mayoría de las veces, solo querrá ejecutar este algoritmo de 10 líneas. Aquí está el código".
Léon Pelletier
31
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. Ingenuo en el mejor de los casos. Utilice una biblioteca de serialización json real.
Sleeper Smith
112

Esta respuesta menciona Json.NET pero no le dice cómo puede usar Json.NET para serializar un diccionario:

return JsonConvert.SerializeObject( myDictionary );

A diferencia de JavaScriptSerializer, myDictionaryno tiene que ser un diccionario de tipo <string, string>para que JsonConvert funcione.

Big McLargeHuge
fuente
71

Json.NET probablemente serializa los diccionarios de C # de manera adecuada ahora, pero cuando el OP originalmente publicó esta pregunta, muchos desarrolladores de MVC pueden haber estado utilizando la clase JavaScriptSerializer porque esa era la opción predeterminada lista para usar .

Si está trabajando en un proyecto heredado (MVC 1 o MVC 2) y no puede usar Json.NET, le recomiendo que use un en List<KeyValuePair<K,V>>lugar de un Dictionary<K,V>>. La clase JavaScriptSerializer heredada serializará este tipo muy bien, pero tendrá problemas con un diccionario.

Documentación: serialización de colecciones con Json.NET

Jim G.
fuente
3
Respuesta perfecta para usuarios de asp.net mvc3 y mvc4
Gomes
JsonConvert.SerializeObject no parece manejar la serialización de diccionarios de C # a un tipo de colección enumerable cuando se lee de nuevo en Javascript. Por el contrario, crea un objeto donde cada par de la colección C # ahora es una propiedad / valor simple en un objeto, que no se puede enumerar fácilmente como una colección. Entonces, a menos que tenga una mala versión de nuget, Json.NET todavía no es adecuado.
StingyJack
Oh si. Ya estaba haciendo algo similar, pero tratando de encontrar otra manera, y me topé con esto. Sentí que podría ser útil informar a otros para evitar el agujero del conejo Json.NET para este artículo (de lo contrario funciona muy bien).
StingyJack
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Json;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<int, List<int>> foo = new Dictionary<int, List<int>>();

            foo.Add(1, new List<int>( new int[] { 1, 2, 3, 4 }));
            foo.Add(2, new List<int>(new int[] { 2, 3, 4, 1 }));
            foo.Add(3, new List<int>(new int[] { 3, 4, 1, 2 }));
            foo.Add(4, new List<int>(new int[] { 4, 1, 2, 3 }));

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<int, List<int>>));

            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, foo);
                Console.WriteLine(Encoding.Default.GetString(ms.ToArray()));
            }
        }
    }
}

Esto escribirá en la consola:

[{\"Key\":1,\"Value\":[1,2,3,4]},{\"Key\":2,\"Value\":[2,3,4,1]},{\"Key\":3,\"Value\":[3,4,1,2]},{\"Key\":4,\"Value\":[4,1,2,3]}]
Merritt
fuente
19

Respuesta simple de una línea

( using System.Web.Script.Serialization)

Este código será convertir cualquier Dictionary<Key,Value>a Dictionary<string,string>y luego serializarlo como una cadena JSON:

var json = new JavaScriptSerializer().Serialize(yourDictionary.ToDictionary(item => item.Key.ToString(), item => item.Value.ToString()));

Vale la pena señalar que algo así Dictionary<int, MyClass>también se puede serializar de esta manera mientras se preserva el tipo / objeto complejo.


Explicación (desglose)

var yourDictionary = new Dictionary<Key,Value>(); //This is just to represent your current Dictionary.

Puede reemplazar la variable yourDictionarycon su variable real.

var convertedDictionary = yourDictionary.ToDictionary(item => item.Key.ToString(), item => item.Value.ToString()); //This converts your dictionary to have the Key and Value of type string.

Hacemos esto, porque tanto la clave como el valor deben ser de tipo cadena, como requisito para la serialización de a Dictionary.

var json = new JavaScriptSerializer().Serialize(convertedDictionary); //You can then serialize the Dictionary, as both the Key and Value is of type string, which is required for serialization.
HowlinWulf
fuente
No tengo JavaScriptSerializer en mi C #.
Jonny
1
@ Jonny, falta el ensamblaje de referencia System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob
He leído que System.Web.Extensionsno está en la versión de Client Framework, pero también requiere la versión completa.
vapcguy
Podría ser una solución para aplicaciones limitadas, pero forzar todos los valores a escribir string no producirá el JSON correcto si alguna propiedad del objeto no es type string.
Suncat2000
1
La mejor respuesta sobre este tema.
T.Todua
12

Lo siento si la sintaxis es mínima, pero el código del que obtengo esto estaba originalmente en VB :)

using System.Web.Script.Serialization;

...

Dictionary<int,List<int>> MyObj = new Dictionary<int,List<int>>();

//Populate it here...

string myJsonString = (new JavaScriptSerializer()).Serialize(MyObj);
Riwalk
fuente
2
Lanza ArgumentException: el tipo 'System.Collections.Generic.Dictionary`2 no es compatible para la serialización / deserialización de un diccionario, las claves deben ser cadenas u objetos.
Pavel Chuchuva
7

En Asp.net Core use:

using Newtonsoft.Json

var obj = new { MyValue = 1 };
var json = JsonConvert.SerializeObject(obj);
var obj2 = JsonConvert.DeserializeObject(json);
Skorunka František
fuente
Hice referencia System.Corey luego intenté hacer referencia using Newtonsoft.Jsony sin alegría. Creo que Newtonsoftes una biblioteca de terceros.
vapcguy
2
@vapcguy Sí, Newtonsoft es de terceros, pero es ampliamente utilizado y adoptado también por MS en sus productos. nuget.org/packages/Newtonsoft.Json
Skorunka František
7

Puedes usar System.Web.Script.Serialization.JavaScriptSerializer:

Dictionary<string, object> dictss = new Dictionary<string, object>(){
   {"User", "Mr.Joshua"},
   {"Pass", "4324"},
};

string jsonString = (new JavaScriptSerializer()).Serialize((object)dictss);
MaxEcho
fuente
2

Aquí le mostramos cómo hacerlo utilizando solo bibliotecas .Net estándar de Microsoft ...

using System.IO;
using System.Runtime.Serialization.Json;

private static string DataToJson<T>(T data)
{
    MemoryStream stream = new MemoryStream();

    DataContractJsonSerializer serialiser = new DataContractJsonSerializer(
        data.GetType(),
        new DataContractJsonSerializerSettings()
        {
            UseSimpleDictionaryFormat = true
        });

    serialiser.WriteObject(stream, data);

    return Encoding.UTF8.GetString(stream.ToArray());
}
David Young
fuente
Podemos combinar esto con Dictionary<string, dynamic>y tener todos los tipos primitivos JSON como números enteros, flotantes, booleanos, cadenas, incluso nulos y dentro de un objeto. +1
Christos Lytras
1

Puedes usar JavaScriptSerializer .

Doce47
fuente
¿son serializables los diccionarios?
Numenor
Pensé que esto funcionaría: string json = serializer.Serialize ((object) dict);
Doce47
1
@Numenor Sí, lo son, pero solo si la clave Y el valor son de tipo string. He publicado una respuesta aquí que incluye eso, si quieres echar un vistazo.
HowlinWulf
@HowlinWulf para ser más exactos, el valor no tiene que ser una cadena. Pero para la clave, definitivamente no puede ser un int. Las cuerdas funcionan mejor como clave.
Gyum Fox
1
@ Twelve47 Debería incluir un uso de muestra, en caso de que ese enlace se mueva alguna vez. De lo contrario, esta respuesta podría volverse inútil algún día.
vapcguy 01 de
1

Parece que hay muchas bibliotecas diferentes y lo que no parece haber ido y venido en los años anteriores. Sin embargo, a partir de abril de 2016, esta solución funcionó bien para mí. Cadenas fácilmente reemplazables por ints .

TL / DR; Copie esto si es por eso que vino aquí:

    //outputfilename will be something like: "C:/MyFolder/MyFile.txt"
    void WriteDictionaryAsJson(Dictionary<string, List<string>> myDict, string outputfilename)
    {
        DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Dictionary<string, List<string>>));
        MemoryStream ms = new MemoryStream();
        js.WriteObject(ms, myDict); //Does the serialization.

        StreamWriter streamwriter = new StreamWriter(outputfilename);
        streamwriter.AutoFlush = true; // Without this, I've run into issues with the stream being "full"...this solves that problem.

        ms.Position = 0; //ms contains our data in json format, so let's start from the beginning
        StreamReader sr = new StreamReader(ms); //Read all of our memory
        streamwriter.WriteLine(sr.ReadToEnd()); // and write it out.

        ms.Close(); //Shutdown everything since we're done.
        streamwriter.Close();
        sr.Close();
    }

Dos puntos de importación. Primero, asegúrese de agregar System.Runtime.Serliazation como referencia en su proyecto dentro del Explorador de soluciones de Visual Studio. Segundo, agrega esta línea,

using System.Runtime.Serialization.Json;

en la parte superior del archivo con el resto de sus usos, para que DataContractJsonSerializerpueda encontrar la clase. Esta publicación de blog tiene más información sobre este método de serialización.

Formato de datos (entrada / salida)

Mis datos son un diccionario con 3 cadenas, cada una apuntando a una lista de cadenas. Las listas de cadenas tienen longitudes 3, 4 y 1. Los datos se ven así:

StringKeyofDictionary1 => ["abc","def","ghi"]
StringKeyofDictionary2 => ["String01","String02","String03","String04"]
Stringkey3 => ["someString"]

La salida escrita en el archivo estará en una línea, aquí está la salida formateada:

 [{
     "Key": "StringKeyofDictionary1",
     "Value": ["abc",
     "def",
     "ghi"]
 },
 {
     "Key": "StringKeyofDictionary2",
     "Value": ["String01",
     "String02",
     "String03",
     "String04",
 ]
 },
 {
     "Key": "Stringkey3",
     "Value": ["SomeString"]
 }]
mwjohnson
fuente
0

Esto es similar a lo que Meritt ha publicado anteriormente. simplemente publicando el código completo

    string sJSON;
    Dictionary<string, string> aa1 = new Dictionary<string, string>();
    aa1.Add("one", "1"); aa1.Add("two", "2"); aa1.Add("three", "3");
    Console.Write("JSON form of Person object: ");

    sJSON = WriteFromObject(aa1);
    Console.WriteLine(sJSON);

    Dictionary<string, string> aaret = new Dictionary<string, string>();
    aaret = ReadToObject<Dictionary<string, string>>(sJSON);

    public static string WriteFromObject(object obj)
    {            
        byte[] json;
            //Create a stream to serialize the object to.  
        using (MemoryStream ms = new MemoryStream())
        {                
            // Serializer the object to the stream.  
            DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
            ser.WriteObject(ms, obj);
            json = ms.ToArray();
            ms.Close();
        }
        return Encoding.UTF8.GetString(json, 0, json.Length);

    }

    // Deserialize a JSON stream to object.  
    public static T ReadToObject<T>(string json) where T : class, new()
    {
        T deserializedObject = new T();
        using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {

            DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedObject.GetType());
            deserializedObject = ser.ReadObject(ms) as T;
            ms.Close();
        }
        return deserializedObject;
    }
Karshan
fuente
0

Si su contexto lo permite (restricciones técnicas, etc.), use el JsonConvert.SerializeObjectmétodo de Newtonsoft.Json : le facilitará la vida.

Dictionary<string, string> localizedWelcomeLabels = new Dictionary<string, string>();
localizedWelcomeLabels.Add("en", "Welcome");
localizedWelcomeLabels.Add("fr", "Bienvenue");
localizedWelcomeLabels.Add("de", "Willkommen");
Console.WriteLine(JsonConvert.SerializeObject(localizedWelcomeLabels));

// Outputs : {"en":"Welcome","fr":"Bienvenue","de":"Willkommen"}
Ishikawa
fuente