Serializzazione di un elenco su JSON


182

Ho un modello a oggetti che assomiglia a questo:

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

La proprietà ObjectInJsonè una versione già serializzata di un oggetto che contiene elenchi nidificati. Per il momento, sto serializzando l'elenco di MyObjectInJsonmanualmente in questo modo:

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

Mi chiedo se posso sostituire questo tipo di codice pericoloso con JavascriptSerializere ottenere gli stessi risultati. Come lo farei?

Grazie.


Si noti che in un progetto WPF, è necessario aggiungere un riferimento System.Web.Extensionsda utilizzare System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Andrew,

Risposte:


338

Se si utilizza .Net Core 3.0 o successivo;

L'impostazione predefinita è l'utilizzo dell'implementazione del System.Text.Jsonparser integrata .

per esempio

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

in alternativa, sono disponibili altre opzioni meno tradizionali come il parser Utf8Json e Jil : questi possono offrire prestazioni superiori , se ne hai davvero bisogno, ma dovrai installare i rispettivi pacchetti.

Se bloccato usando .Net Core 2.2 o precedente;

L'impostazione predefinita è l'utilizzo di Newtonsoft JSON.Net come parser JSON di prima scelta.

per esempio

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

potrebbe essere necessario installare prima il pacchetto.

PM> Install-Package Newtonsoft.Json

Per maggiori dettagli vedi e vota la risposta che è la fonte di queste informazioni .

Solo come riferimento, questa era la risposta originale, molti anni fa;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);

1
ah ok, serializza ANCHE elenchi di oggetti e non solo oggetti stessi. Grazie.
frenchie,

non piacciono le relazioni cicliche, ma questo non è un problema qui
Jodrell,

13
Si noti che questo spazio dei nomi è nascosto in modo astuto in System.Web.Extensions. Dopo averlo aggiunto come riferimento, la soluzione funziona alla perfezione!
Guru a otto bit,

1
Vedo la tua risposta modificata e vorrei davvero avere un esempio aggiornato.
Dylan Brams,

1
@ IamNumber5 già fornito nell'altra risposta. Ho comunque esteso la mia risposta.
Jodrell,

111

Puoi anche usare Json.NET. Basta scaricarlo da http://james.newtonking.com/pages/json-net.aspx , estrarre il file compresso e aggiungerlo come riferimento.

Quindi serializza l'elenco (o qualunque oggetto tu voglia) con il seguente:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Aggiornamento: è anche possibile aggiungerlo al progetto tramite Gestione pacchetti NuGet (Strumenti -> Gestione pacchetti NuGet -> Console Gestione pacchetti):

PM> Install-Package Newtonsoft.Json

Documentazione: serializzazione delle raccolte


12

Esistono due modi comuni per farlo con i serializzatori JSON integrati:

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

    Nota che questa opzione richiede la definizione di un contratto dati per la tua classe:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }

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

4

.NET supporta già la serializzazione Json di base tramite lo spazio dei nomi System.Runtime.Serialization.Json e la classe DataContractJsonSerializer dalla versione 3.5. Come suggerisce il nome, DataContractJsonSerializer prende in considerazione tutte le annotazioni di dati aggiunte agli oggetti per creare l'output Json finale.

Ciò può essere utile se si dispone già di classi di dati annotate che si desidera serializzare Json su uno stream, come descritto in Procedura: serializzare e deserializzare i dati JSON . Ci sono limitazioni ma è abbastanza buono e abbastanza veloce se hai esigenze di base e non vuoi aggiungere ancora un'altra libreria al tuo progetto.

Il codice seguente serializza un elenco nel flusso di output della console. Come vedi, è un po ' più dettagliato di Json.NET e non sicuro (ovvero senza generici)

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

D'altra parte, Json.NET offre un controllo molto migliore su come si genera Json. Questo sarà MOLTO utile quando devi mappare nomi di nomi compatibili con javascript a classi .NET, formattare date a json ecc.

Un'altra opzione è ServiceStack.Text , parte dello stack ServicStack ..., che fornisce un set di serializzatori molto veloci per Json, JSV e CSV.


0

basandomi su una risposta di un altro post .. Ho escogitato un modo più generico per compilare un elenco, utilizzando il recupero dinamico con Json.NET versione 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;
    }
}

chiamare per elaborare

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

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

o questa chiamata per l'elaborazione

{
        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));
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.