Como converter um dicionário em uma string JSON em c #?

130

Eu quero converter minha Dictionary<int,List<int>>string JSON. Alguém sabe como conseguir isso em c #?

daehaai
fonte
3
Use o pacote nuget newtonSoft.json. JsonConvert.SerializeObject (yourObject)
RayLoveless

Respostas:

118

Serializar estruturas de dados contendo apenas valores numéricos ou booleanos é bastante simples. Se você não tiver muito o que serializar, poderá escrever um método para seu tipo específico.

Para a Dictionary<int, List<int>>como você especificou, você pode usar o 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) + "}";
}

Mas, se você estiver serializando várias classes diferentes, ou estruturas de dados mais complexas, ou especialmente se seus dados contiverem valores de sequência , seria melhor usar uma biblioteca JSON respeitável que já saiba lidar com coisas como caracteres de escape e quebras de linha. Json.NET é uma opção popular.

gilly3
fonte
66
Esta solução é ingênua na melhor das hipóteses. Use uma biblioteca de serialização json real.
jacobsimeon
131
@Jacob - Ingênuo? Ai. Pessoalmente, não posso justificar a inclusão de outra montagem quando tudo o que preciso fazer pode ser realizado com um método curto e simples.
gilly3
16
Mais um + no comentário gilly3. Em algum momento você está codificando no Windows Phone. Você está adicionando zlip, twitter, google, material de processamento de áudio e material de processamento de imagem. É melhor implementar um método simples como esse e alguns HttpRequests básicos para interação em mídias sociais, se o seu uso for simples. Ao adicionar uma montagem, você sempre precisa lidar com bugs e com a impossibilidade de obter uma versão lite. A propósito, dentro de json libs, existem métodos ingênuos como este e nenhuma mágica.
Léon Pelletier
14
Deve haver uma página em cada projeto aberto dizendo: "Ei, na maioria das vezes, você só deseja executar esse algo de 10 linhas. Aqui está o código."
Léon Pelletier
31
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM. Ingênuo na melhor das hipóteses. Use uma biblioteca de serialização json real.
Sleeper Smith
112

Esta resposta menciona o Json.NET, mas deixa de lhe dizer como você pode usar o Json.NET para serializar um dicionário:

return JsonConvert.SerializeObject( myDictionary );

Ao contrário do JavaScriptSerializer, myDictionarynão precisa ser um dicionário do tipo <string, string>para o JsonConvert funcionar.

Big McLargeHuge
fonte
71

O Json.NET provavelmente serializa dicionários de C # adequadamente agora, mas quando o OP postou originalmente essa pergunta, muitos desenvolvedores do MVC podem estar usando a classe JavaScriptSerializer porque essa era a opção padrão pronta para uso.

Se você estiver trabalhando em um projeto legado (MVC 1 ou MVC 2) e não puder usar o Json.NET, recomendo usar um em List<KeyValuePair<K,V>>vez de a Dictionary<K,V>>. A classe herdada JavaScriptSerializer serializará esse tipo muito bem, mas terá problemas com um dicionário.

Documentation: Serializando coleções com o Json.NET

Jim G.
fonte
3
Resposta perfeita para ASP.NET MVC3 e mvc4 usuários
Gomes
JsonConvert.SerializeObject não parece manipular dicionários c # de serialização para um tipo de coleção enumerável quando lida novamente em Javascript. Em vez disso, cria um objeto em que cada par na coleção C # agora é uma propriedade / valor simples em um objeto, que não pode ser facilmente enumerado como uma coleção. Portanto, a menos que eu tenha uma versão ruim do nuget, o Json.NET ainda não é adequado.
StingyJack
Ai sim. Eu já estava fazendo uma coisa semelhante, mas tentando descobrir outra maneira, e me deparei com isso. Achei que seria útil informar outras pessoas para evitar a toca de coelho do Json.NET para este item (funciona muito bem caso contrário).
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()));
            }
        }
    }
}

Isso gravará no 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]}]
mérito
fonte
19

Resposta simples de uma linha

( using System.Web.Script.Serialization)

Este código irá converter qualquer Dictionary<Key,Value>para Dictionary<string,string>e, em seguida, serializá-lo como uma string JSON:

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

Vale a pena notar que algo assim Dictionary<int, MyClass>também pode ser serializado dessa maneira, preservando o tipo / objeto complexo.


Explicação (discriminação)

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

Você pode substituir a variável yourDictionarypela sua variável real.

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.

Fazemos isso, porque a chave e o valor precisam ser do tipo string, como requisito para serialização de 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
fonte
Não tenho JavaScriptSerializer no meu c #.
Jonny
1
@ Jonny, você está perdendo o assembly de referência System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob
Eu li que System.Web.Extensionsnão está na versão Client Framework, mas requer a versão completa também.
vapcguy
Pode ser uma solução para aplicativos limitados, mas forçar todos os valores a digitar string não produzirá o JSON correto se alguma propriedade do objeto não for do tipo string.
precisa saber é o seguinte
1
melhor resposta sobre este tópico.
T.Todua
12

Desculpe se a sintaxe está um pouquinho menor, mas o código do qual estou obtendo estava originalmente no 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
fonte
2
Ele lança ArgumentException: o tipo 'System.Collections.Generic.Dictionary`2 não é suportado para serialização / desserialização de um dicionário, as chaves devem ser cadeias de caracteres ou objetos.
Pavel Chuchuva
7

No uso do Asp.net Core:

using Newtonsoft.Json

var obj = new { MyValue = 1 };
var json = JsonConvert.SerializeObject(obj);
var obj2 = JsonConvert.DeserializeObject(json);
Skorunka František
fonte
Eu referenciei System.Coree tentei referenciar using Newtonsoft.Jsone sem alegria. Eu acho que Newtonsofté uma biblioteca de terceiros.
vapcguy
2
@vapcguy Sim, a Newtonsoft é de terceiros, mas amplamente utilizada e adotada também pela MS em seus produtos. Você pode
usar o seguinte
7

Você pode usar 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
fonte
2

Veja como fazê-lo usando apenas bibliotecas .Net padrão da 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
fonte
Podemos combinar isso Dictionary<string, dynamic>e ter todos os tipos primitivos JSON, como intergers, floats, booleanos, strings e até nulos e dentro de um objeto. +1
Christos Lytras
1

Você poderia usar JavaScriptSerializer .

Twelve47
fonte
os dicionários são serializáveis?
Numenor
Eu teria pensado que isso iria funcionar - string json = serializer.Serialize ((object) dict);
Twelve47
1
@Numenor Sim, eles são, mas apenas se a Chave E o Valor forem do tipo string. Postei aqui uma resposta que inclui isso, se você quiser dar uma olhada.
precisa saber é o seguinte
@ HowlinWulf para ser mais exato, o valor não precisa ser uma string. Mas, para a chave, não pode ser definitivamente um int. Strings funcionam melhor como chave.
Gyum Fox
1
@ Twelve47 Deve incluir uma amostra de uso, caso esse link seja movido. Caso contrário, essa resposta poderá se tornar inútil, um dia.
vapcguy
1

Parece muitas bibliotecas diferentes e o que parece não ter surgido nos anos anteriores. No entanto, em abril de 2016, essa solução funcionou bem para mim. Strings facilmente substituídos por ints .

TL / DR; Copie isso se é para isso que você veio aqui:

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

Dois pontos de importação. Primeiro, certifique-se de adicionar System.Runtime.Serliazation como referência no seu projeto no Solution Explorer do Visual Studio. Segundo, adicione esta linha,

using System.Runtime.Serialization.Json;

na parte superior do arquivo, com o restante de seus usos, para que a DataContractJsonSerializerclasse seja encontrada. Esta postagem do blog tem mais informações sobre esse método de serialização.

Formato de Dados (Entrada / Saída)

Meus dados são um dicionário com três strings, cada um apontando para uma lista de strings. As listas de cadeias têm comprimentos 3, 4 e 1. Os dados são assim:

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

A saída gravada no arquivo estará em uma linha, aqui está a saída formatada:

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

Isso é semelhante ao que Meritt postou anteriormente. apenas postando o código 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;
    }
Karshan
fonte
0

Se o seu contexto permitir (restrições técnicas, etc.), use o JsonConvert.SerializeObjectmétodo da Newtonsoft.Json : facilitará sua vida.

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
fonte