Serializando uma lista para JSON

182

Eu tenho um modelo de objeto que se parece com isso:

public MyObjectInJson
{
   public long ObjectID {get;set;}
   public string ObjectInJson {get;set;}
}

A propriedade ObjectInJsoné uma versão já serializada, um objeto que contém listas aninhadas. Por enquanto, estou serializando a lista MyObjectInJsonmanualmente desta forma:

StringBuilder TheListBuilder = new StringBuilder();

TheListBuilder.Append("[");
int TheCounter = 0;

foreach (MyObjectInJson TheObject in TheList)
{
  TheCounter++;
  TheListBuilder.Append(TheObject.ObjectInJson);

  if (TheCounter != TheList.Count())
  {
    TheListBuilder.Append(",");
  }
}
TheListBuilder.Append("]");

return TheListBuilder.ToString();

Gostaria de saber se posso substituir esse tipo de código perigoso JavascriptSerializere obter os mesmos resultados. Como eu faria isso?

Obrigado.

frenchie
fonte
Observe que, em um projeto WPF, você precisa adicionar uma referência a System.Web.Extensionsser usada System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Andrew

Respostas:

338

Se estiver usando o .Net Core 3.0 ou posterior;

O padrão é usar a System.Text.Jsonimplementação do analisador interno.

por exemplo

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

como alternativa, outras opções menos populares estão disponíveis, como o analisador Utf8Json e Jil : elas podem oferecer desempenho superior , se você realmente precisar, mas precisará instalar os respectivos pacotes.

Se preso usando o .Net Core 2.2 ou anterior;

O padrão é usar o Newtonsoft JSON.Net como sua primeira escolha do Analisador JSON.

por exemplo

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

pode ser necessário instalar o pacote primeiro.

PM> Install-Package Newtonsoft.Json

Para obter mais detalhes, consulte e vote com antecedência a resposta que é a fonte dessas informações .

Apenas para referência, esta foi a resposta original, há muitos anos;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
fonte
1
ah ok, também serializa listas de objetos e não apenas objetos em si. Obrigado.
22412
doesen't como relações cíclicas mas isso não é um problema aqui
Jodrell
13
Observe que esse espaço para nome é astuciosamente escondido em System.Web.Extensions. Depois de adicionar isso como referência, a solução funciona de maneira brilhante!
Guru de oito bits
1
Vejo sua resposta editada e realmente gostaria de ter um exemplo atualizado.
Dylan Brams
1
@ IamNumber5 já fornecido na outra resposta. Estendi minha resposta de qualquer maneira.
Jodrell
111

Você também pode usar o Json.NET. Basta fazer o download em http://james.newtonking.com/pages/json-net.aspx , extrair o arquivo compactado e adicioná-lo como referência.

Em seguida, basta serializar a lista (ou qualquer objeto que você desejar) com o seguinte:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Atualização: você também pode adicioná-lo ao seu projeto pelo Gerenciador de Pacotes NuGet (Ferramentas -> Gerenciador de Pacotes NuGet -> Console do Gerenciador de Pacotes):

PM> Install-Package Newtonsoft.Json

Documentação: serializando coleções

Brent Barbata
fonte
12

Há duas maneiras comuns de fazer isso com os serializadores JSON internos:

  1. JavaScriptSerializer

    var serializer = new JavaScriptSerializer();
    return serializer.Serialize(TheList);
    
  2. DataContractJsonSerializer

    var serializer = new DataContractJsonSerializer(TheList.GetType());
    using (var stream = new MemoryStream())
    {
        serializer.WriteObject(stream, TheList);
        using (var sr = new StreamReader(stream))
        {
            return sr.ReadToEnd();
        }
    }
    

    Observe que essa opção requer a definição de um contrato de dados para sua classe:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }
    
Joulukuusi
fonte
5
public static string JSONSerialize<T>(T obj)
        {
            string retVal = String.Empty;
            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                serializer.WriteObject(ms, obj);
                var byteArray = ms.ToArray();
                retVal = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
            }
            return retVal;
        }
samsanthosh2008
fonte
4

O .NET já suporta serialização Json básica por meio do espaço para nome System.Runtime.Serialization.Json e a classe DataContractJsonSerializer desde a versão 3.5. Como o nome indica, o DataContractJsonSerializer leva em consideração as anotações de dados adicionadas aos seus objetos para criar a saída Json final.

Isso pode ser útil se você já tiver classes de dados anotadas que deseja serializar o Json em um fluxo, conforme descrito em Como: Serializar e Deserializar Dados JSON . Existem limitações, mas é suficientemente bom e rápido o suficiente se você tiver necessidades básicas e não quiser adicionar ainda outra biblioteca ao seu projeto.

O código a seguir serializa uma lista para o fluxo de saída do console. Como você vê, é um pouco mais detalhado que o Json.NET e não é seguro para tipos (ou seja, sem genéricos)

        var list = new List<string> {"a", "b", "c", "d"};

        using(var output = Console.OpenStandardOutput())                
        {                
            var writer = new DataContractJsonSerializer(typeof (List<string>));
            writer.WriteObject(output,list);
        }

Por outro lado, o Json.NET fornece um controle muito melhor sobre como você gera o Json. Isso será muito útil quando você precisar mapear nomes de nomes compatíveis com javascript para classes .NET, datas de formato para json etc.

Outra opção é o ServiceStack.Text , parte da pilha ServicStack ..., que fornece um conjunto de serializadores muito rápidos para Json, JSV e CSV.

Panagiotis Kanavos
fonte
0

baseando-me em uma resposta de outra postagem. Eu criei uma maneira mais genérica de criar uma lista, utilizando recuperação dinâmica com o Json.NET versão 12.x

using Newtonsoft.Json;

static class JsonObj
{
    /// <summary>
    /// Deserializes a json file into an object list
    /// Author: Joseph Poirier 2/26/2019
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public static List<T> DeSerializeObject<T>(string fileName)
    {
        List<T> objectOut = new List<T>();

        if (string.IsNullOrEmpty(fileName)) { return objectOut; }

        try
        {
            // reading in full file as text
            string ss = File.ReadAllText(fileName);

            // went with <dynamic> over <T> or <List<T>> to avoid error..
            //  unexpected character at line 1 column 2
            var output = JsonConvert.DeserializeObject<dynamic>(ss);

            foreach (var Record in output)
            {
                foreach (T data in Record)
                {
                    objectOut.Add(data);
                }
            }
        }
        catch (Exception ex)
        {
            //Log exception here
            Console.Write(ex.Message);
        }

        return objectOut;
    }
}

chamada para processar

{
        string fname = "../../Names.json"; // <- your json file path

        // for alternate types replace string with custom class below
        List<string> jsonFile = JsonObj.DeSerializeObject<string>(fname);
}

ou esta chamada para processar

{
        string fname = "../../Names.json"; // <- your json file path

        // for alternate types replace string with custom class below
        List<string> jsonFile = new List<string>();
        jsonFile.AddRange(JsonObj.DeSerializeObject<string>(fname));
}
Joseph Poirier
fonte