Сериализация списка в JSON

182

У меня есть объектная модель, которая выглядит так:

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

Свойство ObjectInJsonпредставляет собой уже сериализованную версию объекта, содержащего вложенные списки. На данный момент я сериализирую список MyObjectInJsonвручную следующим образом:

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

Интересно, смогу ли я заменить этот опасный код JavascriptSerializerи получить те же результаты? Как бы я это сделал?

Спасибо.

Frenchie
источник
Обратите внимание, что в проекте WPF необходимо добавить ссылку System.Web.Extensionsна использование System.Web.Script.Serialization: stackoverflow.com/a/18746092/1599699 stackoverflow.com/a/19299695/1599699
Эндрю

Ответы:

338

При использовании .Net Core 3.0 или более поздней версии;

По умолчанию используется встроенный System.Text.Json синтаксический анализатор.

например

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

в качестве альтернативы доступны другие, менее распространенные варианты, такие как Utf8Json parser и Jil : они могут предложить превосходную производительность , если вам это действительно нужно, но вам нужно будет установить соответствующие пакеты.

Если застрять с использованием .Net Core 2.2 или более ранней версии;

По умолчанию используется Newtonsoft JSON.Net в качестве первого выбора JSON Parser.

например

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

вам может понадобиться сначала установить пакет.

PM> Install-Package Newtonsoft.Json

Для получения более подробной информации см. И ответьте на вопрос, который является источником этой информации .

Только для справки, это был оригинальный ответ много лет назад;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
источник
1
ну ладно, ТАКЖЕ сериализует списки объектов, а не только сами объекты. Спасибо.
Французский
не люблю циклические отношения, но это не проблема
Джодрелл
13
Обратите внимание, что это пространство имен хитро спрятано в System.Web.Extensions. Как только вы добавите это в качестве ссылки, решение работает великолепно!
Восьмиразрядный гуру
1
Я вижу ваш отредактированный ответ и очень хочу, чтобы у меня был обновленный пример.
Дилан Брамс
1
@ IamNumber5 уже указан в другом ответе. Я все равно расширил свой ответ.
Джодрелл
111

Вы также можете использовать Json.NET. Просто скачайте его по адресу http://james.newtonking.com/pages/json-net.aspx , извлеките сжатый файл и добавьте его в качестве ссылки.

Затем просто сериализуйте список (или любой другой объект) с помощью следующего:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Обновление: вы также можете добавить его в свой проект с помощью диспетчера пакетов NuGet (Инструменты -> Диспетчер пакетов NuGet -> Консоль диспетчера пакетов):

PM> Install-Package Newtonsoft.Json

Документация: сериализация коллекций

Брент Барбата
источник
12

Есть два распространенных способа сделать это с помощью встроенных сериализаторов 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();
        }
    }

    Обратите внимание, что этот параметр требует определения контракта данных для вашего класса:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }
Joulukuusi
источник
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
источник
4

.NET уже поддерживает базовую сериализацию Json через пространство имен System.Runtime.Serialization.Json и DataContractJsonSerializer. класс начиная с версии 3.5. Как следует из названия, DataContractJsonSerializer учитывает любые аннотации данных, которые вы добавляете к своим объектам для создания окончательного вывода Json.

Это может быть удобно, если у вас уже есть аннотированные классы данных, которые вы хотите сериализовать Json в поток, как описано в разделе Практическое руководство. Сериализация и десериализация данных JSON. . Существуют ограничения, но это достаточно хорошо и достаточно быстро, если у вас есть базовые потребности и вы не хотите добавлять в свой проект еще одну библиотеку.

Следующий код сериализует список в поток вывода консоли. Как вы видите, он немного более многословен, чем Json.NET, и не является типобезопасным (то есть не имеет обобщений)

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

С другой стороны, Json.NET обеспечивает гораздо лучший контроль над тем, как вы генерируете Json. Это очень ОЧЕНЬ удобно, когда вам нужно сопоставить имена, дружественные к JavaScript, к классам .NET, форматировать даты в json и т. Д.

Другим вариантом является ServiceStack.Text , часть стека ServicStack ..., который предоставляет набор очень быстрых сериализаторов для Json, JSV и CSV.

Панагиотис Канавос
источник
0

основанный на ответе из другого сообщения. Я придумала более общий способ составления списка, используя динамический поиск с Json.NET версии 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;
    }
}

призыв к процессу

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

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

или этот призыв к процессу

{
        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));
}
Джозеф Пуарье
источник