Serializacja listy do JSON

182

Mam model obiektu, który wygląda następująco:

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

Właściwość ObjectInJsonjest już serializowaną wersją obiektu, który zawiera zagnieżdżone listy. Na razie serializuję listę MyObjectInJsonręcznie w następujący sposób:

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

Zastanawiam się, czy mogę zastąpić tego rodzaju niebezpiecznym kodem JavascriptSerializeri uzyskać takie same wyniki. Jak mam to zrobić?

Dzięki.

Frenchie
źródło
Zauważ, że w projekcie WPF musisz dodać odniesienie System.Web.Extensionsdo użycia System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Andrew

Odpowiedzi:

338

Jeśli używasz .Net Core 3.0 lub nowszy;

Domyślnie używa wbudowanej System.Text.Jsonimplementacji parsera.

na przykład

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

alternatywnie dostępne są inne, mniej popularne opcje, takie jak parser Utf8Json i Jil : Mogą one oferować lepszą wydajność , jeśli naprawdę tego potrzebujesz, ale będziesz musiał zainstalować odpowiednie pakiety.

Jeśli utknął przy użyciu .Net Core 2.2 lub wcześniejszej;

Domyślnie używany jest NewSoft JSON.Net jako pierwszy wybór JSON Parser.

na przykład

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

może być konieczne najpierw zainstalowanie pakietu.

PM> Install-Package Newtonsoft.Json

Aby uzyskać więcej informacji, zobacz i głosuj odpowiedź, która jest źródłem tych informacji .

Tylko w celach informacyjnych to była pierwotna odpowiedź sprzed wielu lat;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
źródło
1
ah ok, również szereguje listy obiektów, a nie tylko same obiekty. Dzięki.
frenchie
nie lubią cyklicznych związków, ale to nie jest problem
Jodrell
13
Zauważ, że ta przestrzeń nazw jest sprytnie schowana w System.Web.Extensions. Gdy dodasz to jako odniesienie, rozwiązanie działa doskonale!
Ośmiobitowy Guru z
1
Widzę twoją zredagowaną odpowiedź i naprawdę chciałbym mieć zaktualizowany przykład.
Dylan Brams,
1
@ IamNumber5 już podany w innej odpowiedzi. I tak udzieliłem odpowiedzi.
Jodrell
111

Możesz także użyć Json.NET. Wystarczy go pobrać ze strony http://james.newtonking.com/pages/json-net.aspx , wyodrębnić skompresowany plik i dodać jako odniesienie.

Następnie po prostu serializuj listę (lub dowolny inny obiekt), wykonując następujące czynności:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Aktualizacja: możesz również dodać go do swojego projektu za pomocą Menedżera pakietów NuGet (Narzędzia -> Menedżer pakietów NuGet -> Konsola Menedżera pakietów):

PM> Install-Package Newtonsoft.Json

Dokumentacja: Serializacja zbiorów

Brent Barbata
źródło
12

Istnieją dwa typowe sposoby, aby to zrobić za pomocą wbudowanych serializatorów JSON:

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

    Pamiętaj, że ta opcja wymaga zdefiniowania kontraktu danych dla twojej klasy:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }
Joulukuusi
źródło
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
źródło
4

.NET obsługuje już podstawową serializację Json za pośrednictwem przestrzeni nazw System.Runtime.Serialization.Json i klasy DataContractJsonSerializer od wersji 3.5. Jak sama nazwa wskazuje, DataContractJsonSerializer uwzględnia wszelkie adnotacje danych dodane do obiektów w celu utworzenia ostatecznego wyniku Json.

Może to być przydatne, jeśli masz już klasy danych z adnotacjami, które chcesz serializować Json do strumienia, jak opisano w Poradnik: szeregowanie i deserializacja danych JSON . Istnieją ograniczenia, ale jest wystarczająco dobry i szybki, jeśli masz podstawowe potrzeby i nie chcesz dodawać jeszcze kolejnej biblioteki do swojego projektu.

Poniższy kod serializuje listę do strumienia wyjściowego konsoli. Jak widzisz, jest nieco bardziej szczegółowy niż Json.NET i nie jest bezpieczny dla typu (tzn. Nie ma generycznych)

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

Z drugiej strony Json.NET zapewnia znacznie lepszą kontrolę nad sposobem generowania Jsona. Będzie to BARDZO przydatne, gdy trzeba mapować nazwy nazw przyjazne dla javascript na klasy .NET, formatować daty na json itp.

Inną opcją jest ServiceStack.Text , część stosu ServicStack ..., który zapewnia zestaw bardzo szybkich serializatorów dla Json, JSV i CSV.

Panagiotis Kanavos
źródło
0

bazując na odpowiedzi z innego posta. Wymyśliłem bardziej ogólny sposób na zbudowanie listy, wykorzystując dynamiczne pobieranie z Json.NET w wersji 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;
    }
}

wezwanie do przetworzenia

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

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

lub to wezwanie do przetworzenia

{
        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
źródło