Sérialisation d'une liste en JSON

182

J'ai un modèle objet qui ressemble à ceci:

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

La propriété ObjectInJsonest une version déjà sérialisée d'un objet qui contient des listes imbriquées. Pour le moment, je sérialise la liste MyObjectInJsonmanuellement comme ceci:

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

Je me demande si je peux remplacer ce genre de code dangereux par JavascriptSerializeret obtenir les mêmes résultats. Comment ferais-je cela?

Merci.

frenchie
la source
Notez que dans un projet WPF, vous devez ajouter une référence à System.Web.Extensionspour utiliser System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Andrew

Réponses:

338

Si vous utilisez .Net Core 3.0 ou version ultérieure;

Par défaut, utilisez l' System.Text.Jsonimplémentation de l'analyseur intégré

par exemple

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

Alternativement, d'autres options moins courantes sont disponibles comme l' analyseur Utf8Json et Jil : elles peuvent offrir des performances supérieures , si vous en avez vraiment besoin, mais vous devrez installer leurs packages respectifs.

En cas de blocage avec .Net Core 2.2 ou version antérieure;

Par défaut, utilisez Newtonsoft JSON.Net comme analyseur JSON de premier choix.

par exemple

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

vous devrez peut-être d'abord installer le package.

PM> Install-Package Newtonsoft.Json

Pour plus de détails, consultez et votez pour la réponse qui est la source de ces informations .

Pour référence seulement, c'était la réponse originale, il y a de nombreuses années;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
la source
1
ah ok, il sérialise AUSSI des listes d'objets et pas seulement des objets eux-mêmes. Merci.
frenchie
n'aime pas les relations cycliques mais ce n'est pas un problème ici
Jodrell
13
Notez que cet espace de noms est astucieusement caché dans System.Web.Extensions. Une fois que vous ajoutez cela comme référence, la solution fonctionne à merveille!
Gourou de huit bits
1
Je vois votre réponse modifiée et j'aimerais vraiment avoir un exemple mis à jour.
Dylan Brams
1
@ IamNumber5 déjà fourni dans l'autre réponse. J'ai quand même prolongé ma réponse.
Jodrell
111

Vous pouvez également utiliser Json.NET. Téléchargez-le simplement sur http://james.newtonking.com/pages/json-net.aspx , extrayez le fichier compressé et ajoutez-le comme référence.

Ensuite, sérialisez simplement la liste (ou l'objet de votre choix) avec ce qui suit:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Mise à jour: vous pouvez également l'ajouter à votre projet via le gestionnaire de package NuGet (Outils -> Gestionnaire de package NuGet -> Console du gestionnaire de package):

PM> Install-Package Newtonsoft.Json

Documentation: sérialisation des collections

Brent Barbata
la source
12

Il existe deux façons courantes de le faire avec les sérialiseurs JSON intégrés:

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

    Notez que cette option nécessite la définition d'un contrat de données pour votre classe:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }
    
Joulukuusi
la source
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
la source
4

.NET prend déjà en charge la sérialisation Json de base via l' espace de noms System.Runtime.Serialization.Json et la classe DataContractJsonSerializer depuis la version 3.5. Comme son nom l'indique, DataContractJsonSerializer prend en compte toutes les annotations de données que vous ajoutez à vos objets pour créer la sortie Json finale.

Cela peut être pratique si vous avez déjà des classes de données annotées que vous souhaitez sérialiser Json dans un flux, comme décrit dans Comment: sérialiser et désérialiser les données JSON . Il y a des limitations mais c'est assez bon et assez rapide si vous avez des besoins de base et ne voulez pas ajouter Yet Another Library à votre projet.

Le code suivant sérialise une liste dans le flux de sortie de la console. Comme vous le voyez, il est un peu plus détaillé que Json.NET et non de type sécurisé (c'est-à-dire pas de génériques)

        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'autre part, Json.NET offre un bien meilleur contrôle sur la façon dont vous générez Json. Cela sera TRÈS pratique lorsque vous devrez mapper des noms de noms compatibles avec javascript à des classes .NET, formater des dates en json, etc.

Une autre option est ServiceStack.Text , qui fait partie de la pile ServicStack ..., qui fournit un ensemble de sérialiseurs très rapides pour Json, JSV et CSV.

Panagiotis Kanavos
la source
0

en me basant sur une réponse d'une autre publication. J'ai trouvé un moyen plus générique de créer une liste, en utilisant la récupération dynamique avec Json.NET version 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;
    }
}

appel à traiter

{
        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 cet appel à traiter

{
        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
la source