Comment convertir un dictionnaire en chaîne JSON en C #?

131

Je veux convertir ma Dictionary<int,List<int>>chaîne en JSON. Quelqu'un sait-il comment y parvenir en C #?

daehaai
la source
3
Utilisez le package nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Réponses:

118

La sérialisation des structures de données contenant uniquement des valeurs numériques ou booléennes est assez simple. Si vous n'avez pas grand-chose à sérialiser, vous pouvez écrire une méthode pour votre type spécifique.

Pour un Dictionary<int, List<int>>comme vous l'avez spécifié, vous pouvez utiliser 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) + "}";
}

Mais, si vous sérialisez plusieurs classes différentes, ou des structures de données plus complexes, ou surtout si vos données contiennent des valeurs de chaîne , vous feriez mieux d'utiliser une bibliothèque JSON réputée qui sait déjà comment gérer des choses comme les caractères d'échappement et les sauts de ligne. Json.NET est une option populaire.

gilly3
la source
67
Cette solution est au mieux naïve. Utilisez une véritable bibliothèque de sérialisation json.
jacobsimeon
131
@Jacob - Naïf? Aie. Personnellement, je ne peux pas justifier l'inclusion d' un autre assemblage alors que tout ce que j'ai à faire peut être accompli avec une méthode courte et simple.
gilly3
16
Encore un commentaire sur gilly3. Parfois, vous codez sur Windows Phone. Vous ajoutez zlip, twitter, google, du traitement audio, du traitement d'image. Vous feriez mieux d'implémenter une méthode simple comme celle-ci, et quelques HttpRequests de base pour l'interaction avec les médias sociaux si votre utilisation est simple. Lors de l'ajout d'un assembly, vous devez toujours faire face à des bugs et à l'impossibilité d'obtenir une version allégée. Au fait, à l'intérieur des bibliothèques json, il existe des méthodes naïves comme celle-ci et aucune magie.
Léon Pelletier
14
Il devrait y avoir une page sur chaque projet ouvert vous disant: "Hé, la plupart du temps, vous ne voudrez exécuter que cet algo de 10 lignes. Voici le code."
Léon Pelletier
32
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. Au mieux, naïf. Utilisez une véritable bibliothèque de sérialisation json.
Sleeper Smith
112

Cette réponse mentionne Json.NET mais s'arrête avant de vous dire comment vous pouvez utiliser Json.NET pour sérialiser un dictionnaire:

return JsonConvert.SerializeObject( myDictionary );

Contrairement à JavaScriptSerializer, il myDictionaryn'est pas nécessaire <string, string>que JsonConvert fonctionne comme un dictionnaire de type .

Grand McLargeÉnorme
la source
71

Json.NET sérialise probablement correctement les dictionnaires C # maintenant, mais lorsque l'OP a initialement publié cette question, de nombreux développeurs MVC utilisaient peut-être la classe JavaScriptSerializer , car c'était l'option par défaut prête à l'emploi .

Si vous travaillez sur un projet existant (MVC 1 ou MVC 2), et vous ne pouvez pas utiliser Json.NET, je vous recommande d'utiliser un au List<KeyValuePair<K,V>>lieu d'un Dictionary<K,V>>. La classe héritée JavaScriptSerializer sérialisera très bien ce type, mais elle aura des problèmes avec un dictionnaire.

Documentation: sérialisation des collections avec Json.NET

Jim G.
la source
3
Réponse parfaite pour les utilisateurs asp.net mvc3 et mvc4
Gomes
JsonConvert.SerializeObject ne semble pas gérer la sérialisation des dictionnaires c # en un type de collection énumérable lors de la relecture en Javascript. Au contraire, cela crée un objet où chaque paire de la collection C # est maintenant une propriété / valeur simple dans un objet, qui ne peut pas être facilement énumérée comme une collection. Donc, à moins d'avoir une mauvaise version de nuget, Json.NET n'est toujours pas adéquat à cet égard.
StingyJack
Oh oui. Je faisais déjà une chose similaire, mais j'essayais de trouver une autre façon, et je suis tombé dessus. J'ai pensé qu'il pourrait être utile de faire savoir aux autres d'éviter le trou de lapin Json.NET pour cet article (fonctionne très bien sinon).
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()));
            }
        }
    }
}

Cela écrira sur la 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]}]
Merritt
la source
19

Réponse simple en une ligne

( using System.Web.Script.Serialization)

Ce code convertira tout Dictionary<Key,Value>en Dictionary<string,string>, puis le sérialisera en tant que chaîne JSON:

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

Il est intéressant de noter que quelque chose comme Dictionary<int, MyClass>peut également être sérialisé de cette manière tout en préservant le type / objet complexe.


Explication (ventilation)

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

Vous pouvez remplacer la variable yourDictionarypar votre variable réelle.

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.

Nous faisons cela, car la clé et la valeur doivent être de type chaîne, comme condition requise pour la sérialisation d'un fichier 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
la source
Je n'ai pas JavaScriptSerializer dans mon C #.
Jonny
1
@Jonny il vous manque l'assembly de référence System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob
J'ai lu que ce System.Web.Extensionsn'est pas dans la version Client Framework, mais nécessite également la version complète.
vapcguy
Cela pourrait être une solution pour des applications limitées, mais forcer toutes les valeurs à taper string ne donnera pas le JSON correct si les propriétés d'objet ne sont pas de type string.
Suncat2000
1
meilleure réponse sur ce sujet.
T.Todua
12

Désolé si la syntaxe est la plus petite, mais le code à partir duquel je l'obtiens était à l'origine 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
la source
2
Il lève ArgumentException: le type 'System.Collections.Generic.Dictionary`2 n'est pas pris en charge pour la sérialisation / désérialisation d'un dictionnaire, les clés doivent être des chaînes ou des objets.
Pavel Chuchuva le
7

Dans Asp.net Core, utilisez:

using Newtonsoft.Json

var obj = new { MyValue = 1 };
var json = JsonConvert.SerializeObject(obj);
var obj2 = JsonConvert.DeserializeObject(json);
Skorunka František
la source
J'ai référencé System.Coreet ensuite essayé de référencer using Newtonsoft.Jsonet pas de joie. Je pense que Newtonsoftc'est une bibliothèque tierce.
vapcguy
2
@vapcguy Oui, Newtonsoft est un tiers mais largement utilisé et adopté également par MS dans leurs produits. nuget.org/packages/Newtonsoft.Json
Skorunka František
7

Vous pouvez utiliser 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
la source
2

Voici comment procéder en utilisant uniquement les bibliothèques .Net standard 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
la source
Nous pouvons combiner cela avec Dictionary<string, dynamic>et avoir tous les types primitifs JSON tels que les entiers, les flottants, les booléens, les chaînes, même les valeurs nulles et dans un seul objet. +1
Christos Lytras
1

Vous pouvez utiliser JavaScriptSerializer .

Douze47
la source
les dictionnaires sont-ils sérialisables?
Numenor
J'aurais pensé que cela fonctionnerait - string json = serializer.Serialize ((object) dict);
Twelve47
1
@Numenor Oui, ils le sont, mais seulement si la clé ET la valeur sont de type string. J'ai publié ici une réponse qui inclut cela, si vous voulez jeter un coup d'œil.
HowlinWulf
@HowlinWulf pour être plus précis, la valeur n'a pas besoin d'être une chaîne. Mais pour la clé, ce ne peut pas être définitivement un int. Les cordes fonctionnent le mieux comme clé.
Gyum Fox
1
@ Twelve47 Doit inclure un exemple d'utilisation, au cas où ce lien serait déplacé. Sinon, cette réponse pourrait devenir inutile, un jour.
vapcguy
1

Il semble que beaucoup de bibliothèques différentes et ce qui n'a pas semblé aller et venir au cours des années précédentes. Cependant, en avril 2016, cette solution fonctionnait bien pour moi. Cordes facilement remplacées par des ints .

TL / DR; Copiez ceci si c'est pour cela que vous êtes venu ici:

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

Deux points d'importation. Tout d'abord, assurez-vous d'ajouter System.Runtime.Serliazation comme référence dans votre projet dans l'Explorateur de solutions de Visual Studio. Deuxièmement, ajoutez cette ligne,

using System.Runtime.Serialization.Json;

en haut du fichier avec le reste de vos utilisations, afin que la DataContractJsonSerializerclasse puisse être trouvée. Ce billet de blog contient plus d'informations sur cette méthode de sérialisation.

Format de données (entrée / sortie)

Mes données sont un dictionnaire avec 3 chaînes, chacune pointant vers une liste de chaînes. Les listes de chaînes ont des longueurs 3, 4 et 1. Les données ressemblent à ceci:

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

La sortie écrite dans le fichier sera sur une ligne, voici la sortie formatée:

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

Ceci est similaire à ce que Meritt a publié plus tôt. juste poster le code complet

    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
la source
0

Si votre contexte le permet (contraintes techniques, etc.), utilisez la JsonConvert.SerializeObjectméthode de Newtonsoft.Json : cela vous facilitera la vie.

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
la source