Come faccio a convertire un dizionario in una stringa JSON in C #?


131

Voglio convertire il mio Dictionary<int,List<int>>in stringa JSON. Qualcuno sa come raggiungere questo obiettivo in C #?


3
Utilizzare il pacchetto nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Risposte:


118

La serializzazione di strutture di dati contenenti solo valori numerici o booleani è abbastanza semplice. Se non hai molto da serializzare, puoi scrivere un metodo per il tuo tipo specifico.

Per un Dictionary<int, List<int>>come specificato, è possibile utilizzare 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) + "}";
}

Ma se stai serializzando più classi diverse, o strutture di dati più complesse, o specialmente se i tuoi dati contengono valori di stringa , sarebbe meglio usare una libreria JSON affidabile che sappia già come gestire cose come caratteri di escape e interruzioni di riga. Json.NET è un'opzione popolare.


67
Questa soluzione è ingenua nella migliore delle ipotesi. Utilizzare una libreria di serializzazione json reale.
jacobsimeon,

131
@Jacob - Naive? Ahia. Personalmente, non posso giustificare l'inclusione di un altro assembly quando tutto ciò che devo fare può essere realizzato con un metodo breve e semplice.
gilly3,

16
Ancora un commento + sul commento di gilly3. A volte stai programmando su Windows Phone. Stai aggiungendo zlip, twitter, google, elementi di elaborazione audio, elementi di elaborazione di immagini. Stai meglio implementando un metodo semplice come questo e alcune richieste HTTP di base per l'interazione con i social media se il tuo utilizzo è semplice. Quando si aggiunge un assembly, è sempre necessario gestire i bug e l'impossibilità di ottenere una versione Lite. A proposito, all'interno delle librerie json, ci sono metodi ingenui come questo e nessuna magia.
Léon Pelletier,

14
Dovrebbe esserci una pagina su ogni progetto aperto che ti dice: "Ehi, il più delle volte, vorrai solo eseguire questo algoritmo di 10 righe. Ecco il codice."
Léon Pelletier,

32
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. Ingenuo nella migliore delle ipotesi. Utilizzare una libreria di serializzazione json reale.
Sleeper Smith,

112

Questa risposta menziona Json.NET ma non ti dice come puoi usare Json.NET per serializzare un dizionario:

return JsonConvert.SerializeObject( myDictionary );

A differenza di JavaScriptSerializer, myDictionarynon deve essere un dizionario di tipo <string, string>affinché JsonConvert funzioni.


71

Probabilmente Json.NET ora serializza adeguatamente i dizionari C #, ma quando l'OP originariamente ha pubblicato questa domanda, molti sviluppatori MVC potrebbero aver usato la classe JavaScriptSerializer perché quella era l'opzione predefinita pronta all'uso .

Se stai lavorando a un progetto legacy (MVC 1 o MVC 2) e non riesci a utilizzare Json.NET, ti consiglio di utilizzare un List<KeyValuePair<K,V>>anziché un Dictionary<K,V>>. La classe legacy JavaScriptSerializer serializzerà questo tipo bene, ma avrà problemi con un dizionario.

Documentazione: serializzazione delle raccolte con Json.NET


3
Risposta perfetta per gli utenti di asp.net mvc3 e mvc4
Gomes,

JsonConvert.SerializeObject non sembra gestire la serializzazione di dizionari c # su un tipo di raccolta enumerabile quando viene letta in Javascript. Piuttosto, crea un oggetto in cui ogni coppia nella raccolta C # è ora una semplice proprietà / valore in un oggetto, che non può essere facilmente elencata come una raccolta. Quindi, a meno che non abbia una cattiva versione di Nuget, Json.NET non è ancora adeguato al riguardo.
StingyJack,

Oh si. Stavo già facendo una cosa simile, ma cercavo di scoprire un altro modo e mi sono imbattuto in questo. Ho sentito che potrebbe essere utile far sapere agli altri di evitare la tana del coniglio Json.NET per questo oggetto (altrimenti funziona benissimo).
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()));
            }
        }
    }
}

Questo scriverà sulla console:

[{\"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]}]

19

Risposta semplice su una riga

( using System.Web.Script.Serialization)

Questo codice convertirà qualsiasi Dictionary<Key,Value>in Dictionary<string,string>e quindi lo serializzerà come una stringa JSON:

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

Vale la pena notare che qualcosa di simile Dictionary<int, MyClass>può anche essere serializzato in questo modo preservando il tipo / oggetto complesso.


Spiegazione (guasto)

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

È possibile sostituire la variabile yourDictionarycon la variabile effettiva.

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.

Facciamo questo, perché sia ​​la chiave che il valore devono essere di tipo stringa, come requisito per la serializzazione di 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.

Non ho JavaScriptSerializer nel mio C #.
Jonny il

1
@Jonny non trovi lo System.Web.Extensions montaggio di riferimento msdn.microsoft.com/en-us/library/...
aminhotob

Ho letto che System.Web.Extensionsnon è nella versione Client Framework, ma richiede anche la versione completa.
vapcguy,

Potrebbe essere una soluzione per applicazioni limitate, ma forzare tutti i valori per digitare string non produrrà il JSON corretto se qualsiasi proprietà dell'oggetto non è di tipo string.
Suncat2000,

1
migliore risposta su questo argomento.
T.Todua,

12

Scusate se la sintassi è la più piccola, ma il codice da cui sto ottenendo era originariamente in 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);

2
Genera ArgumentException: digitare 'System.Collections.Generic.Dictionary`2 non è supportato per la serializzazione / deserializzazione di un dizionario, le chiavi devono essere stringhe o oggetti.
Pavel Chuchuva,


7

In Asp.net Core utilizzare:

using Newtonsoft.Json

var obj = new { MyValue = 1 };
var json = JsonConvert.SerializeObject(obj);
var obj2 = JsonConvert.DeserializeObject(json);

Ho fatto riferimento System.Coree quindi ho cercato di fare riferimento using Newtonsoft.Jsone nessuna gioia. Penso che Newtonsoftsia una libreria di terze parti.
vapcguy,

2
@vapcguy Sì, Newtonsoft è di terze parti ma ampiamente utilizzato e adottato anche dagli Stati Uniti nei loro prodotti. nuget.org/packages/Newtonsoft.Json
Skorunka František

7

Puoi usare 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);

2

Ecco come farlo utilizzando solo le librerie .Net standard di 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());
}

Possiamo combinare questo con Dictionary<string, dynamic>e avere tutti i tipi primitivi JSON come interger, float, booleani, stringhe, anche null e all'interno di un oggetto. +1
Christos Lytras,

1

È possibile utilizzare JavaScriptSerializer .


i dizionari sono serializzabili?
Numenor,

Avrei pensato che avrebbe funzionato - string json = serializer.Serialize ((object) dict);
Dodici47,

1
@Numenor Sì, lo sono, ma solo se Key AND Value sono di tipo string. Ho pubblicato qui una risposta che lo include, se vuoi dare un'occhiata.
HowlinWulf, l'

@HowlinWulf per essere più precisi, il valore non deve essere una stringa. Ma per la chiave, non può assolutamente essere un int. Le stringhe funzionano meglio come chiave.
Gyum Fox,

1
@ Twelve47 Dovrebbe includere un utilizzo di esempio, nel caso in cui tale collegamento venga mai spostato. Altrimenti questa risposta potrebbe diventare inutile, un giorno.
vapcguy,

1

Sembra un sacco di librerie diverse e ciò che non è sembrato andare e venire negli anni precedenti. Tuttavia, a partire da aprile 2016, questa soluzione ha funzionato bene per me. Stringhe facilmente sostituibili da ints .

TL / DR; Copia questo se è per questo che sei venuto qui:

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

Due punti di importazione. Innanzitutto, assicurarsi di aggiungere System.Runtime.Serliazation come riferimento nel progetto all'interno di Esplora soluzioni di Visual Studio. Secondo, aggiungi questa riga,

using System.Runtime.Serialization.Json;

nella parte superiore del file con il resto dei tuoi utilizzi, quindi la DataContractJsonSerializerclasse può essere trovata. Questo post sul blog contiene ulteriori informazioni su questo metodo di serializzazione.

Formato dati (input / output)

I miei dati sono un dizionario con 3 stringhe, ognuna che punta a un elenco di stringhe. Gli elenchi di stringhe hanno lunghezze 3, 4 e 1. I dati si presentano così:

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

L'output scritto nel file sarà su una riga, ecco l'output formattato:

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

0

Questo è simile a quello che Meritt ha pubblicato in precedenza. basta pubblicare il codice 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;
    }

0

Se il tuo contesto lo consente (vincoli tecnici, ecc.), Utilizza il JsonConvert.SerializeObjectmetodo di Newtonsoft.Json : ti semplificherà la vita.

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"}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.