Serializar una lista a JSON

182

Tengo un modelo de objeto que se ve así:

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

La propiedad ObjectInJsones una versión ya serializada, un objeto que contiene listas anidadas. Por el momento, estoy serializando la lista de forma MyObjectInJsonmanual de esta manera:

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

Me pregunto si puedo reemplazar este tipo de código peligroso JavascriptSerializery obtener los mismos resultados. ¿Cómo haría esto?

Gracias.

frenchie
fuente
Tenga en cuenta que en un proyecto WPF, debe agregar una referencia System.Web.Extensionspara usar System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Andrew

Respuestas:

338

Si usa .Net Core 3.0 o posterior;

Valor predeterminado para usar la System.Text.Jsonimplementación del analizador incorporado .

p.ej

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

alternativamente, hay otras opciones menos convencionales disponibles, como el analizador Utf8Json y Jil : pueden ofrecer un rendimiento superior , si realmente lo necesita, pero deberá instalar sus respectivos paquetes.

Si se atasca usando .Net Core 2.2 o anterior;

Predeterminado para usar Newtonsoft JSON.Net como su primer analizador JSON.

p.ej

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

Es posible que primero deba instalar el paquete.

PM> Install-Package Newtonsoft.Json

Para obtener más detalles, consulte y vote a favor la respuesta que es la fuente de esta información .

Solo como referencia, esta fue la respuesta original, hace muchos años;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
fuente
1
ah ok, TAMBIÉN serializa listas de objetos y no solo objetos en sí. Gracias.
frenchie
no le gustan las relaciones cíclicas, pero eso no es un problema aquí
Jodrell
13
Tenga en cuenta que este espacio de nombres está astutamente escondido en System.Web.Extensions. Una vez que agregue eso como referencia, ¡la solución funciona de manera brillante!
Eight-Bit Guru
1
Veo su respuesta editada y realmente desearía tener un ejemplo actualizado.
Dylan Brams
1
@ IamNumber5 ya se proporciona en la otra respuesta. Extendí mi respuesta de todos modos.
Jodrell
111

También puedes usar Json.NET. Simplemente descárguelo en http://james.newtonking.com/pages/json-net.aspx , extraiga el archivo comprimido y agréguelo como referencia.

Luego, solo serialice la lista (o el objeto que desee) con lo siguiente:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Actualización: también puede agregarlo a su proyecto a través del Administrador de paquetes NuGet (Herramientas -> Administrador de paquetes NuGet -> Consola del Administrador de paquetes):

PM> Install-Package Newtonsoft.Json

Documentación: Serialización de colecciones

Brent Barbata
fuente
12

Hay dos formas comunes de hacerlo con los serializadores JSON integrados:

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

    Tenga en cuenta que esta opción requiere la definición de un contrato de datos para su clase:

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

.NET ya admite la serialización básica de Json a través del espacio de nombres System.Runtime.Serialization.Json y la clase DataContractJsonSerializer desde la versión 3.5. Como su nombre lo indica, DataContractJsonSerializer tiene en cuenta cualquier anotación de datos que agregue a sus objetos para crear la salida final de Json.

Eso puede ser útil si ya ha anotado clases de datos que desea serializar Json en una secuencia, como se describe en Cómo: Serializar y deserializar datos JSON . Existen limitaciones, pero es lo suficientemente bueno y rápido si tiene necesidades básicas y no desea agregar Yet Another Library a su proyecto.

El siguiente código serializa una lista a la secuencia de salida de la consola. Como puede ver, es un poco más detallado que Json.NET y no es seguro para escribir (es decir, no 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 otro lado, Json.NET proporciona un control mucho mejor sobre cómo generar Json. Esto será MUY útil cuando tenga que asignar nombres de nombres compatibles con javascript a clases .NET, formatear fechas a json, etc.

Otra opción es ServiceStack.Text , parte de la pila ServicStack ..., que proporciona un conjunto de serializadores muy rápidos para Json, JSV y CSV.

Panagiotis Kanavos
fuente
0

basándose en una respuesta de otra publicación. Se me ocurrió una forma más genérica de crear una lista, utilizando la recuperación dinámica con Json.NET versión 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;
    }
}

llamar para procesar

{
        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 esta llamada para procesar

{
        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
fuente