Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 242 243 244 245 246 247 248 249 250 ... 407
имен System.Xml.Serialization. В табл. 20.12 описаны некоторые (но не все) атрибуты .NET Core, влияющие на способ кодирования данных XML в потоке.

Разумеется, для управления тем, как XmlSerializer генерирует результирующий XML-документ, можно использовать многие другие атрибуты .NET Core. Полные сведения ищите в описании пространства имен System.Xml.Serialization в документации по .NET Core.

На заметку! Класс XmlSerializer требует, чтобы все сериализируемые типы в графе объектов поддерживали стандартный конструктор (поэтому обязательно добавьте его обратно, если вы определяете специальные конструкторы).

Сериализация объектов с использованием XmlSerializer

Добавьте в свой файл Program.cs следующую локальную функцию:

static void SaveAsXmlFormat<T>(T objGraph, string fileName)

{

  // В конструкторе XmlSerializer должен быть объявлен тип.

  XmlSerializer xmlFormat = new XmlSerializer(typeof(T));

  using (Stream fStream = new FileStream(fileName,

    FileMode.Create, FileAccess.Write, FileShare.None))

  {

    xmlFormat.Serialize(fStream, objGraph);

  }

}

Добавьте к операторам верхнего уровня такой код:

SaveAsXmlFormat(jbc, "CarData.xml");

Console.WriteLine("=> Saved car in XML format!");

SaveAsXmlFormat(p, "PersonData.xml");

Console.WriteLine("=> Saved person in XML format!");

Заглянув внутрь сгенерированного файла CarData.xml, вы обнаружите в нем показанные ниже XML-данные:

<?xml version="1.0"?>

<JamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:xsd= "http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com">

  <TheRadio>

    <HasTweeters>true</HasTweeters>

    <HasSubWoofers>false</HasSubWoofers>

    <StationPresets>

      <double>89.3</double>

      <double>105.1</double>

      <double>97.1</double>

    </StationPresets>

    <RadioId>XF-552RR6</RadioId>

  </TheRadio>

  <IsHatchBack>false</IsHatchBack>

  <CanFly>true</CanFly>

  <CanSubmerge>false</CanSubmerge>

</JamesBondCar>

Если вы хотите указать специальное пространство имен XML, которое уточняет JamesBondCar и кодирует значения canFly и canSubmerge в виде атрибутов XML, тогда модифицируйте определение класса JamesBondCar следующим образом:

[Serializable, XmlRoot(Namespace = "http://www.MyCompany.com")]

public class JamesBondCar : Car

{

  [XmlAttribute]

  public bool CanFly;

  [XmlAttribute]

  public bool CanSubmerge;

...

}

Вот как будет выглядеть результирующий XML-документ (обратите внимание на открывающий элемент <JamesBondCar>):

<?xml version="1.0"""?>

<JamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema"

  CanFly="true" CanSubmerge="false" xmlns="http://www.MyCompany.com">

...

</JamesBondCar>

Исследуйте содержимое файла PersonData.xml:

<?xml version="1.0"?>

<Person xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance

  xmlns:xsd= "http://www.w3.org/2001/XMLSchema">

  <IsAlive>true</IsAlive>

  <FirstName>James</FirstName>

</Person>

Важно отметить, что свойство PersonAge не сериализируется в XML. Это подтверждает, что сериализация XML учитывает только открытые свойства и поля.

Сериализация коллекций объектов

Теперь, когда вы видели, каким образом сохранять одиночный объект в потоке, давайте посмотрим,как сохранить набор объектов. Создайте локальную функцию, которая инициализирует список объектов JamesBondCar и сериализирует его в XML:

static void SaveListOfCarsAsXml()

{

  // Сохранить список List<T> объектов JamesBondCar.

  List<JamesBondCar> myCars = new()

    {

      new JamesBondCar{CanFly = true, CanSubmerge = true},

      new JamesBondCar{CanFly = true, CanSubmerge = false},

      new JamesBondCar{CanFly = false, CanSubmerge = true},

      new JamesBondCar{CanFly = false, CanSubmerge = false},

    };

  using (Stream fStream = new FileStream("CarCollection.xml",

    FileMode.Create, FileAccess.Write, FileShare.None))

  {

    XmlSerializer xmlFormat = new XmlSerializer(typeof(List<JamesBondCar>));

    xmlFormat.Serialize(fStream, myCars);

  }

  Console.WriteLine("=> Saved list of cars!");

}

Наконец, добавьте следующую строку, чтобы задействовать новую функцию:

SaveListOfCarsAsXml(); 

Десериализация объектов и коллекций объектов

Десериализация XML буквально противоположна сериализации объектов (и коллекций объектов). Рассмотрим показанную далее локальную функцию для десериализации XML-разметки обратно в граф объектов. И снова обратите внимание, что тип, с которым нужно работать, должен быть передан конструктору XmlSerializer:

static T ReadAsXmlFormat<T>(string fileName)

{

  // Создать типизированный экземпляр класса XmlSerializer.

  XmlSerializer xmlFormat = new XmlSerializer(typeof(T));

  using (Stream fStream = new FileStream(fileName, FileMode.Open))

  {

    T obj = default;

    obj = (T)xmlFormat.Deserialize(fStream);

    return obj;

  }

}

Добавьте к операторам верхнего уровня следующий код, чтобы восстановить XML-разметку обратно в объекты (или списки объектов):

JamesBondCar savedCar = ReadAsXmlFormat<JamesBondCar>("CarData.xml");

Console.WriteLine("Original Car: {0}",savedCar.ToString());

Console.WriteLine("Read Car: {0}",savedCar.ToString());

List<JamesBondCar> savedCars =

    ReadAsXmlFormat<List<JamesBondCar>>("CarCollection.xml");

Сериализация и десериализация с помощью System.Text.Json

 В пространстве имен System.Text.Json имеется класс System.Text.Json.JsonSerializer, который вы можете использовать для сохранения открытого состояния заданного объекта как данных JSON.

Управление генерацией данных JSON

 По умолчанию JsonSerializer сериализирует все открытые свойства в виде пар "имя-значение" в формате JSON, применяя такие же имена (и регистр символов), как у имен свойств объекта. Вы можете управлять многими аспектами процесса сериализации с помощью наиболее часто используемых атрибутов, перечисленных в табл. 20.13.

Сериализация объектов с использованием JsonSerializer

Класс JsonSerializer содержит статические методы Serialize(), применяемые для преобразования объектов .NET Core (включая графы объектов) в строковое представление открытых свойств. Данные представляются как пары "имя-значение" в формате JSON. Добавьте в файл Program.cs показанную ниже локальную функцию:

static void SaveAsJsonFormat<T>(T objGraph, string fileName)

{

  File.WriteAllText(fileName,

      System.Text.Json.JsonSerializer.Serialize(objGraph));

}

Добавьте к своим операторам верхнего уровня следующий код:

SaveAsJsonFormat(jbc, "CarData.json");

Console.WriteLine("=> Saved car in JSON format!");

SaveAsJsonFormat(p, "PersonData.json");

Console.WriteLine("=> Saved person in JSON format!");

Когда вы будете исследовать файлы JSON, вас может удивить тот факт, что файл CarData.json пуст (не считая пары фигурных скобок), а файл PersonData.json содержит только значение Firstname. Причина в том, что JsonSerializer по умолчанию записывает только открытые свойства, но не открытые поля. Проблема решается в следующем разделе.

Включение полей

Включить открытые поля в генерируемые данные JSON можно двумя способами. Первый способ предусматривает использование класса JsonSerializerOptions для сообщения JsonSerializer о необходимости включить все поля. Второй способ предполагает модификацию классов за счет добавления атрибута [Jsonlnclude] к каждому открытому полю, которое должно быть включено в вывод JSON. Обратите внимание, что при первом способе

1 ... 242 243 244 245 246 247 248 249 250 ... 407
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен бесплатно.

Оставить комментарий