Как преобразовать словарь в строку JSON в C #?

131

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

daehaai
источник
3
Используйте пакет nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless 01

Ответы:

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, которая уже знает, как обрабатывать такие вещи, как escape-символы и разрывы строк. Json.NET - популярный вариант.

gilly3
источник
67
Это решение в лучшем случае наивно. Используйте настоящую библиотеку сериализации json.
jacobsimeon
131
@ Джейкоб - Наивный? Уч. Лично я не могу оправдать включение еще одной сборки, когда все, что мне нужно сделать, можно выполнить одним коротким и простым методом.
gilly3
16
Еще один + к комментарию gilly3. Иногда вы пишете код на Windows Phone. Вы добавляете zlip, twitter, google, средства обработки звука, средства обработки изображений. Вам лучше реализовать простой метод, подобный этому, и некоторые базовые HttpRequests для взаимодействия с социальными сетями, если ваше использование простое. При добавлении сборки всегда приходится сталкиваться с ошибками и невозможностью получить облегченную версию. Кстати, внутри json libs есть такие наивные методы и никакой магии.
Леон Пеллетье
14
В каждом открытом проекте должна быть страница с сообщением: «Эй, в большинстве случаев вам нужно выполнить только этот 10-строчный алгоритм. Вот код».
Леон Пеллетье
32
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. В лучшем случае наивно. Используйте настоящую библиотеку сериализации json.
Sleeper Smith
112

В этом ответе упоминается Json.NET, но не рассказывается, как вы можете использовать Json.NET для сериализации словаря:

return JsonConvert.SerializeObject( myDictionary );

В отличие от JavaScriptSerializer, для работы JsonConvert myDictionaryне обязательно должен быть словарь типа <string, string>.

Big McLargeHuge
источник
71

Json.NET, вероятно, сейчас адекватно сериализует словари C #, но когда OP изначально разместил этот вопрос, многие разработчики 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.

Мы делаем это, потому что и ключ, и значение должны иметь тип string, как требование для сериализации 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
источник
У меня нет JavaScriptSerializer в моем C #.
Джонни
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);
riwalk
источник
2
Он генерирует исключение ArgumentException: тип System.Collections.Generic.Dictionary`2 не поддерживается для сериализации / десериализации словаря, ключи должны быть строками или объектами.
Павел Чучува
См stackoverflow.com/questions/3685732/...
Павел Chuchuva
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
Скорунка Франтишек
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);
MaxEcho
источник
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, такими как промежуточные числа, числа с плавающей запятой, логические значения, строки и даже нули, и иметь в одном объекте. +1
Христос Литрас
1

Вы можете использовать JavaScriptSerializer .

Twelve47
источник
словари сериализуемы?
Нуменор
Я бы подумал, что это сработает - string json = serializer.Serialize ((object) dict);
Twelve47 08
1
@Numenor Да, но только если ключ И значение имеет тип string. Я опубликовал здесь ответ, который включает это, если вы хотите посмотреть.
HowlinWulf 08
@HowlinWulf, если быть более точным, значение не обязательно должно быть строкой. Но для ключа это точно не может быть int. Струны лучше всего работают как ключ.
Gyum Fox
1
@ Twelve47 Должен включать пример использования на случай, если ссылка когда-либо будет перемещена. Иначе однажды этот ответ может стать бесполезным.
vapcguy 01
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.Serliazation в качестве ссылки в свой проект в обозревателе решений 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"]
 }]
mwjohnson
источник
0

Это похоже на то, что Меритт опубликовал ранее. просто разместите полный код

    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
источник
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"}
Ishikawa
источник