Як перетворити словник у рядок JSON у C #?


131

Я хочу перетворити мою Dictionary<int,List<int>>в рядок JSON. Хтось знає, як цього досягти в C #?


3
Використовуйте новий пакунок newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Відповіді:


118

Серіалізація структур даних, що містять лише числові або булеві значення , досить проста. Якщо вам не потрібно багато серіалізувати, ви можете написати метод для вашого конкретного типу.

Для а Dictionary<int, List<int>>як ви визначили, ви можете використовувати 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) + "}";
}

Але, якщо ви серіалізуєте кілька різних класів або складніші структури даних, або, особливо, якщо ваші дані містять рядкові значення , вам буде краще використовувати поважну бібліотеку JSON, яка вже вміє обробляти такі речі, як символи втечі та розриви рядків. Json.NET - популярний варіант.


66
Це рішення в кращому випадку наївне. Використовуйте справжню бібліотеку серіалізації json.
jacobsimeon

131
@Jacob - наївний? Ой. Особисто я не можу виправдати включення іншої збірки, коли все, що мені потрібно зробити, можна виконати одним коротким і простим методом.
gilly3

16
Ще один + коментар gilly3. Колись ви кодуєте на Windows Phone. Ви додаєте zlip, twitter, google, аудіоінформацію, обробку зображень. Вам краще застосувати простий метод, як він, і деякі основні HttpRequests для взаємодії в соціальних мережах, якщо ваше використання просте. Додаючи збірку, ви завжди маєте справу з помилками та з неможливістю отримати легку версію. До речі, всередині json libs існують такі наївні методи, як магія.
Леон Пелтьє

14
На кожному відкритому проекті повинна бути сторінка, яка говорить вам: "Ей, більшу частину часу ви хочете виконати лише цей алгоритм 10 рядків. Ось код".
Леон Пелтьє

31
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. Наївний у кращому випадку. Використовуйте справжню бібліотеку серіалізації json.
Спіт Сміт

112

Ця відповідь згадує Json.NET, але не зупиняється на тому, як ви можете використовувати Json.NET для серіалізації словника:

return JsonConvert.SerializeObject( myDictionary );

На відміну від JavaScriptSerializer, для роботи JsonConvert myDictionaryне повинен бути словник типу <string, string>.


71

Json.NET, ймовірно, зараз адекватно серіалізує словники C #, але коли ОР спочатку розмістила це запитання, багато розробників MVC, можливо, використовували клас JavaScriptSerializer, оскільки це був параметр за замовчуванням поза полем.

Якщо ви працюєте над застарілим проектом (MVC 1 або MVC 2) і не можете використовувати Json.NET, рекомендую використовувати List<KeyValuePair<K,V>>замість Dictionary<K,V>>. Спадковий клас JavaScriptSerializer буде просто серіалізувати цей тип, але у нього виникнуть проблеми зі словником.

Документація: Серіалізація колекцій за допомогою Json.NET


3
Ідеальна відповідь для користувачів asp.net mvc3 та mvc4
Gomes

Здається, що JsonConvert.SerializeObject не обробляє серіалізуючі словники c # до типу переліченої колекції, коли він читається назад у Javascript. Швидше, це робить об'єкт, де кожна пара в колекції C # тепер є простою властивістю / значенням в об'єкті, яку не можна легко перерахувати як колекцію. Отже, якщо у мене погана версія від nuget, Json.NET все ще не є достатньою.
StingyJack

О, так. Я вже робив подібну річ, але намагався знайти інший шлях і натрапив на це. Я вважав, що може бути корисним повідомити інших, щоб уникнути кролячої ями Json.NET для цього предмета (відмінно працює інакше).
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()));
            }
        }
    }
}

Це буде писати на консоль:

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

Простий однолінійний відповідь

( using System.Web.Script.Serialization)

Цей код перетворить будь-який Dictionary<Key,Value>на, Dictionary<string,string>а потім серіалізує його як рядок JSON:

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

Варто зазначити, що щось подібне Dictionary<int, MyClass>також може бути серіалізовано таким чином, зберігаючи складний тип / об'єкт.


Пояснення (розбивка)

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

Ви можете замінити змінну yourDictionaryфактичною змінною.

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.

Ми робимо це, тому що і Ключ, і Значення повинні бути типів рядка, як вимоги до серіалізації а 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.

У мене в C # немає JavaScriptSerializer.
Джоні

1
@Jonny вам не вистачає довідкової збірки System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob

Я читав, що System.Web.Extensionsйого немає у версії Client Framework, але також потрібна повна версія.
vapcguy

Може бути рішенням для обмежених програм, але примушення всіх значень до введення рядка не призведе до правильного JSON, якщо будь-які властивості об'єкта не є рядком типу.
Suncat2000

1
найкраща відповідь на цю тему.
Т.Тодуа

12

Вибачте, якщо синтаксис є найменшим відколом, але код, з якого я це отримував, був спочатку в 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
Він кидає ArgumentException: Тип 'System.Collections.Generic.Dictionary`2 не підтримується для серіалізації / десеріалізації словника, ключі повинні бути рядками або об'єктами.
Павло Чучува


7

В Asp.net Core використання:

using Newtonsoft.Json

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

Я посилався, System.Coreа потім намагався посилатися using Newtonsoft.Jsonі ніякої радості. Я думаю Newtonsoft, це стороння бібліотека.
vapcguy

2
@vapcguy Так, Newtonsoft є стороннім виробником, але широко використовується і приймається MS у своїх продуктах. nuget.org/packages/Newtonsoft.Json
Skorunka František

7

Ви можете використовувати 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

Ось як це зробити за допомогою лише стандартних бібліотек .Net від 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());
}

Ми можемо поєднати це з Dictionary<string, dynamic>усіма примітивними типами JSON, такими як interger, floats, booleans, strings, навіть null і в межах одного об'єкта. +1
Христос Літрас

1

Ви можете використовувати JavaScriptSerializer .


чи словники серіалізуються?
Нуменор

Я б подумав, що це спрацює - рядок json = serializer.Serialize ((object) dict);
Дванадцять47

1
@Numenor Так, вони є, але лише в тому випадку, якщо Key AND Value мають тип string. Тут я опублікував відповідь, яка включає, що якщо ви хочете подивитися.
HowlinWulf

@HowlinWulf якщо точніше, значення не повинно бути рядком. Але для ключа він точно не може бути цілим. Струни найкраще працюють як ключові.
Gyum Fox

1
@ Twelve47 Потрібно включати вибірку використання, у випадку, якщо посилання коли-небудь перейде. Інакше ця відповідь за один день може стати марною.
vapcguy

1

Здається, багато різних бібліотек, і те, що, здається, не було і минуло протягом попередніх років. Однак станом на квітень 2016 року це рішення спрацювало для мене добре. Струни легко замінюються вкладками .

TL / DR; Скопіюйте це, якщо для цього ви прийшли сюди:

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

Два пункти імпорту. По-перше, не забудьте додати System.Runtime.Serlialization як орієнтир у своєму проекті в Провіднику рішень Visual Studio. По-друге, додайте цей рядок,

using System.Runtime.Serialization.Json;

у верхній частині файлу з рештою ваших прийомів, тому DataContractJsonSerializerклас можна знайти. У цій публікації блогу є додаткова інформація про цей спосіб серіалізації.

Формат даних (введення / вихід)

Мої дані - це словник з 3 рядками, кожен із яких вказує на список рядків. Списки рядків мають довжини 3, 4 та 1. Дані виглядають приблизно так:

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

Вихід, записаний у файл, буде в одному рядку, ось відформатований вихід:

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

0

Це схоже на те, що Meritt опублікував раніше. просто розміщуємо повний код

    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

Якщо ваш контекст дозволяє (технічні обмеження тощо), використовуйте JsonConvert.SerializeObjectметод Newtonsoft.Json : це полегшить ваше життя.

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"}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.