Jak przekonwertować słownik na ciąg JSON w C #?


134

Chcę przekonwertować mój Dictionary<int,List<int>>ciąg na JSON. Czy ktoś wie, jak to osiągnąć w C #?


3
Użyj pakietu nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Odpowiedzi:


120

Serializacja struktur danych zawierających tylko wartości liczbowe lub logiczne jest dość prosta. Jeśli nie masz zbyt wiele do serializacji, możesz napisać metodę dla określonego typu.

Przez Dictionary<int, List<int>>co podałeś, można użyć 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) + "}";
}

Ale jeśli serializujesz kilka różnych klas lub bardziej złożone struktury danych, a zwłaszcza jeśli dane zawierają wartości ciągów , lepiej byłoby użyć renomowanej biblioteki JSON, która już wie, jak obsługiwać takie rzeczy, jak znaki ucieczki i podziały wierszy. Json.NET to popularna opcja.


70
To rozwiązanie jest w najlepszym razie naiwne. Użyj prawdziwej biblioteki serializacji JSON.
jacobsimeon

133
@Jacob - Naiwny? Auć. Osobiście nie mogę usprawiedliwić włączenia kolejnego zestawu, gdy wszystko, co muszę zrobić, można wykonać jedną krótką i prostą metodą.
gilly3

17
Jeszcze jeden + na komentarz gilly3. Czasami piszesz na Windows Phone. Dodajesz zlip, twitter, google, elementy do przetwarzania dźwięku, elementy do przetwarzania obrazu. Lepiej zaimplementuj prostą metodę, taką jak ta, i kilka podstawowych HttpRequests do interakcji w mediach społecznościowych, jeśli twoje użycie jest proste. Podczas dodawania zestawu zawsze musisz radzić sobie z błędami i niemożliwością uzyskania wersji lite. Nawiasem mówiąc, w bibliotekach json są takie naiwne metody i nie ma magii.
Léon Pelletier

14
W każdym otwartym projekcie powinna znajdować się strona informująca: „Hej, w większości przypadków będziesz chciał wykonać tylko te 10 wierszy algo. Oto kod”.
Léon Pelletier

32
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. W najlepszym razie naiwny. Użyj prawdziwej biblioteki serializacji JSON.
Sleeper Smith

117

Ta odpowiedź wspomina o Json.NET, ale nie mówi, jak można użyć Json.NET do serializacji słownika:

return JsonConvert.SerializeObject( myDictionary );

W przeciwieństwie do JavaScriptSerializer myDictionarynie musi być słownikiem typu, <string, string>aby JsonConvert działał.


71

Json.NET prawdopodobnie odpowiednio serializuje słowniki C #, ale kiedy OP pierwotnie opublikował to pytanie, wielu programistów MVC mogło używać klasy JavaScriptSerializer, ponieważ była to domyślna opcja.

Jeśli pracujesz nad starszym projektem (MVC 1 lub MVC 2) i nie możesz używać Json.NET, zalecam użycie pliku List<KeyValuePair<K,V>>zamiast Dictionary<K,V>>. Starsza klasa JavaScriptSerializer będzie mogła serializować ten typ dobrze, ale będzie miała problemy ze słownikiem.

Dokumentacja: serializowanie kolekcji za pomocą Json.NET


3
Idealna odpowiedź dla użytkowników asp.net mvc3 i mvc4
Gomes

JsonConvert.SerializeObject nie wydaje się obsługiwać serializacji słowników C # do typu wyliczalnej kolekcji podczas odczytu z powrotem do JavaScript. Zamiast tego tworzy obiekt, w którym każda para w kolekcji C # jest teraz zwykłą właściwością / wartością w obiekcie, której nie można łatwo wyliczyć jak kolekcji. Tak więc, o ile nie mam złej wersji od nuget, Json.NET nadal nie jest odpowiedni pod tym względem.
StingyJack

O tak. Robiłem już podobną rzecz, ale próbowałem znaleźć inny sposób i natknąłem się na to. Uważam, że warto poinformować innych o unikaniu króliczej nory Json.NET dla tego przedmiotu (w przeciwnym razie działa świetnie).
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()));
            }
        }
    }
}

To napisze do konsoli:

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

20

Prosta odpowiedź w jednej linii

( using System.Web.Script.Serialization)

Ten kod skonwertuje wszystkie Dictionary<Key,Value>na, Dictionary<string,string>a następnie serializuje je jako ciąg JSON:

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

Warto zauważyć, że coś podobnego Dictionary<int, MyClass>można również serializować w ten sposób, zachowując złożony typ / obiekt.


Wyjaśnienie (podział)

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

Możesz zastąpić zmienną yourDictionaryswoją rzeczywistą zmienną.

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.

Robimy to, ponieważ zarówno klucz, jak i wartość muszą być typu string, jako wymaganie do serializacji pliku 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.

Nie mam JavaScriptSerializer w moim C #.
Jonny

1
@Jonny brakuje zestawu referencyjnego System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob

Czytałem, że System.Web.Extensionsnie ma go w wersji Client Framework, ale wymaga też pełnej wersji.
vapcguy

1
najlepsza odpowiedź na ten temat.
T.Todua

1
To powinna być odpowiedź.
GunWanderer

12

Przepraszam, jeśli składnia jest najmniejsza, ale kod, z którego to otrzymuję, był pierwotnie w 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
Zgłasza ArgumentException: typ „System.Collections.Generic.Dictionary” 2 nie jest obsługiwany w przypadku serializacji / deserializacji słownika, klucze muszą być łańcuchami lub obiektami.
Pavel Chuchuva,


7

W Asp.net Core użyj:

using Newtonsoft.Json

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

Odwoływałem się, System.Corea potem próbowałem odwołać się using Newtonsoft.Jsoni bez radości. Myślę, że Newtonsoftjest to biblioteka innej firmy.
vapcguy

2
@vapcguy Tak, Newtonsoft jest firmą zewnętrzną, ale jest szeroko stosowany i przyjęty również przez firmę MS w ich produktach. nuget.org/packages/Newtonsoft.Json
Skorunka František

7

Możesz użyć 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

Oto jak to zrobić, używając tylko standardowych bibliotek .Net firmy 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());
}

Możemy to łączyć Dictionary<string, dynamic>i mieć wszystkie prymitywne typy JSON, takie jak intergers, floats, booleans, stringi, a nawet null w jednym obiekcie. +1
Christos Lytras

1

Możesz użyć JavaScriptSerializer .


czy słowniki można serializować?
Numenor

Myślałem, że to zadziała - string json = serializer.Serialize ((object) dict);
Dwanaście47

1
@Numenor Tak, są, ale tylko wtedy, gdy klucz AND Wartość jest typu string. Opublikowałem tutaj odpowiedź, która zawiera to, jeśli chcesz zobaczyć.
EternalWulf

@HowlinWulf mówiąc dokładniej, wartość nie musi być ciągiem. Ale dla klucza zdecydowanie nie może to być int. Ciągi działają najlepiej jako klucz.
Gyum Fox

1
@ Twelve47 Powinien zawierać przykładowe użycie, na wypadek gdyby ten link został kiedykolwiek przeniesiony. W przeciwnym razie ta odpowiedź pewnego dnia może stać się bezużyteczna.
vapcguy

1

Wydaje się, że jest wiele różnych bibliotek, a to, co nie pojawiło się i nie pojawiło się w poprzednich latach. Jednak od kwietnia 2016 roku to rozwiązanie działało dobrze. Ciągi łatwo zastępowane przez int .

TL / DR; Skopiuj to, jeśli po to tu przyszedłeś:

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

Dwa punkty importu. Najpierw pamiętaj, aby dodać System.Runtime.Serliazation jako odniesienie w projekcie w Eksploratorze rozwiązań programu Visual Studio. Po drugie, dodaj tę linię,

using System.Runtime.Serialization.Json;

u góry pliku z resztą zastosowań, aby DataContractJsonSerializermożna było znaleźć klasę. Ten wpis na blogu zawiera więcej informacji na temat tej metody serializacji.

Format danych (wejście / wyjście)

Moje dane to słownik z 3 ciągami znaków, z których każdy wskazuje listę ciągów. Listy ciągów mają długości 3, 4 i 1. Dane wyglądają następująco:

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

Dane wyjściowe zapisane do pliku będą znajdować się w jednym wierszu, tutaj jest sformatowane wyjście:

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

1

Jeśli pozwala na to kontekst (ograniczenia techniczne itp.), Użyj JsonConvert.SerializeObjectmetody z Newtonsoft.Json : ułatwi Ci to życie.

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

0

Jest to podobne do tego, co opublikował wcześniej Meritt. po prostu zamieszczając cały kod

    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;
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.