Сложные приёмы разработки приложений для Windows Phone 8

Работа с JSON, XML, сжатие данных

Разбить на страницы
Показывать лекцию целиком

Цель работы: освоить технологию работы с форматами JSON и XML и работу со сжатием данных

JSON, XML, сжатие данных

Данные, которые передаются между веб-сервисом и клиентским приложением, кодируют с использованием определенных форматов. Существует множество таких форматов. Например, в ответ на запрос загрузки веб-страницы с веб-сервера могут поступить данные в формате HTML. При работе с API веб-сервисов обычно используются другие форматы, среди них наиболее распространены JSON (Java Script Object Notation) и XML (eXtensible Markup Language). Эти форматы могут использоваться и в задачах, которые не связаны с веб-службами. Например, в XML или JSON могут быть сериализованы объекты (при условии возможности сериализации), состояние которых нужно сохранить в постоянной памяти и загрузить, десериализовав, при очередном запуске приложения.

Как мы увидим ниже, JSON и XML имеют определенные особенности, которые можно учитывать, принимая решение об использовании того или иного формата. С их помощью можно закодировать одни и те же данные, существенная разница между ними будет заключаться в размере полученных данных и в удобстве восприятия данных человеком (нужно обычно при отладке). Ниже мы рассмотрим эти характеристики на практике.

С вопросами передачи и хранения данных тесно связана тема сжатия данных. Сжатие позволяет особым образом обработать данные, получив их представление, имеющее меньший размер, чем исходные данные, но содержащее ту же информацию. В данном случае речь идёт о так называемом сжатии информации без потерь, такое сжатие применимо, например, к документам (или к любым другим данным), когда критически важно точное соответствие данных, хранящихся в исходном документе тем данным, которые получены из сжатой копии документа. Среди алгоритмов сжатия без потерь можно отметить, например, алгоритм .ZIP.

Существует и так называемое сжатие с потерями – оно используется в тех случаях, когда отбрасывание некоторой части информации не ухудшает (или ухудшает незначительно) возможности по работе с информацией. Взамен потери некоторой части информации мы получаем очень большие уровни сжатия. Такое сжатие используется для кодирования изображений (.JPG), звуковых файлов (.MP3), видеофайлов.

Работа с JSON, XML, сжатие данных

Создадим учебное приложение (P7_1), которое демонстрирует работу с JSON, XML и основы работы со сжатыми данными. Воспользуемся шаблоном Приложение Windows Phone. Добавим в приложение новый класс, назовём его ForSerialization и опишем в нём следующие поля и конструктор (Листинг 27.1.)

using System;

namespace P7_1
{
    public class ForSerialization
    {
        //Открытые поля
        public string Line1;
        public int Number1;

        public int[] IntArray;

        public ForSerialization()
        {
            //Инициализация полей
            Line1 = "Пример строки";
            Number1 = 123;

            IntArray = new int[10];

            Random r = new Random();

            for (int i = 0; i < 10; i++)
            {
                IntArray[i] = r.Next() - r.Next();
            }
        }
    }
}

Класс объявлен как общедоступный, это нужно для сериализации, в нём объявлено несколько открытых полей, одно из которых – строка, другое – число, третье поле – это массив, в который мы добавляем десять случайных чисел в конструкторе класса, там же мы инициализируем два других поля.

На главной странице приложения, рис. 27.1., разместим три кнопки. Мы будем размещать код, демонстрирующий интересующие нас техники работы, в обработчиках их событий Click.

(рис 27.1) Страница MainPage

Кроме того, обратите внимание на состав папки References проекта. Здесь мы используем библиотеку Ionic.Zlib для демонстрации работы со сжатыми данными. Существуют и другие библиотеки, подходящие для тех же целей.

В Листинге 27.2 приведен полный код файла MainPage.xaml.cs

using Ionic.Zlib;
using Microsoft.Phone.Controls;
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Xml.Serialization;

namespace P7_1
{

    public partial class MainPage : PhoneApplicationPage
    {
        // Конструктор
        public MainPage()
        {
            InitializeComponent();
        }

        private void cmd_SerializationXML_Click(object sender, RoutedEventArgs e)
        {
            //Объект для сериализации
            ForSerialization ObjectForSerialization = new ForSerialization();

            //Тип данных для сериализации

            Type t = typeof(ForSerialization);

            //XML-сериализатор для объекта
            XmlSerializer XmlS = new XmlSerializer(t);

            //Поток для хранения результатов сериализации
            MemoryStream XmlStr = new MemoryStream();

            //Сериализация в поток
            XmlS.Serialize(XmlStr, ObjectForSerialization);

            //Подготовка к чтению данных из потока
            XmlStr.Position = 0;

            //Средство считывания потока
            StreamReader StRead = new StreamReader(XmlStr);

            //Строка в которую считывается поток
            string XmlString = StRead.ReadToEnd();

            //Вывод строки
            MessageBox.Show(XmlString);

            //Десериализация

            XmlSerializer XmlDS = new XmlSerializer(t);

            //Подготовка потока
            XmlStr.Position = 0;

            //Создаём объект из сериализованных данных
            ForSerialization NewObjectFromXML = XmlDS.Deserialize(XmlStr) as ForSerialization;

            MessageBox.Show("Десериализация завершена");

        }

        private void cmd_SerializationJSON_Click(object sender, RoutedEventArgs e)
        {
            //Объект для сериализации
            ForSerialization ObjectForSerialization = new ForSerialization();

            //Тип данных для сериализации

            Type t = typeof(ForSerialization);

            //JSON-сериализатор
            DataContractJsonSerializer JsS = new DataContractJsonSerializer(t);

            //Поток для хранения результатов сериализации
            MemoryStream JsonStr = new MemoryStream();

            JsS.WriteObject(JsonStr, ObjectForSerialization);

            //Подготовка к чтению данных из потока
            JsonStr.Position = 0;

            //Средство считывания потока
            StreamReader StRead = new StreamReader(JsonStr);

            //Строка в которую считывается поток
            string JsonString = StRead.ReadToEnd();

            //Вывод строки
            MessageBox.Show(JsonString);

            //Десериализация

            DataContractJsonSerializer JsDS = new DataContractJsonSerializer(t);

            //Подготовка потока
            JsonStr.Position = 0;

            //Создаём объект из сериализованных данных
            ForSerialization NewObjectFromJSON = JsDS.ReadObject(JsonStr) as ForSerialization;

            MessageBox.Show("Десериализация завершена");


        }

        private void cmd_Compression_Click(object sender, RoutedEventArgs e)
        {
            string DataForCompression = "Данные для сжатия 1 Данные для сжатия 
2 Данные для сжатия 3";
            //Строка для сжатия, записанная в массив байтов
            Byte[] BytesFromString = System.Text.Encoding.UTF8.GetBytes(DataForCompression);

            //Новый массив, содержащий сжатую строку
            byte[] CompressedData = GZipStream.CompressString(DataForCompression);
            //Строка, восстановленная из сжатых данных
            string Uncompressed = GZipStream.UncompressString(CompressedData);

            MessageBox.Show("Размеры байтовых массивов. Для исходной строки: " + BytesFromString.Length.ToString() + " байт. 
При сжатии: " + CompressedData.Length.ToString() + " байт");
            MessageBox.Show("Исходная строка: (" + DataForCompression + "), строка, 
полученная после сжатия и распаковки: (" + Uncompressed + ").");
        }
    }
}

Обратите внимание на состав директив using. Нам, для работы с рассматриваемыми возможностями, понадобилось подключить некоторые пространства имен, которые, по умолчанию, не подключены.

Рассмотрим код метода cmd_SerializationXML_Click, обработчика события нажатия на кнопку "Сериализация, XML".

Здесь мы сначала создаём объект типа ForSerialization. После создания в конструкторе производится его инициализация, он готов к дальнейшим исследованиям.

В переменную типа Type запишем тип данных объекта – эта переменная понадобится нам при настройке сериализатора. Конечно, необязательно создавать отдельную переменную, тип объекта для сериализации можно получить и в конструкторе сериализатора. Сериализатор – объект типа XmlSerizlizer, создаётся с указанием типа данных, которые мы собираемся сериализовать.

Следующим шагом является создание потока, в данном случае это поток типа MemoryStream, в который мы собираемся записывать сериализованные данные. В качестве потоков могут выступать и другие потоки. Например, те, которые соответствуют открытым файлам.

Метод Serialize объекта типа XmlSerizlizer, выполняет сериализацию. При его вызове указывается, во-первых, поток, в который нужно записать сериализованные данные, во-вторых – объект, который следует сериализовать. После выполнения сериализации наш поток содержит XML-представление объекта, мы можем, при практическом использовании данного механизма, отправить это представление по сети, сохранить на диск. Сейчас мы хотим получить строковое представление потока для того, чтобы просмотреть его. Для этого мы сначала устанавливаем указатель потока на его первую позицию, затем создаём объект типа StreamReader, с помощью которого можно прочитать поток. Мы будем читать его в строку XmlString и выводить на экран в виде сообщения, которое можно прочитать. Это сообщение будет содержать следующий текст:

<?xml version="1.0" encoding="utf-8" ?> 
- <ForSerialization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<Line1>Пример строки</Line1> 
<Number1>123</Number1> 
- <IntArray> 
<int>-518451200</int> 
<int>-463632356</int> 
<int>1312024067</int> 
<int>689675499</int> 
<int>-43902912</int> 
<int>-202627666</int> 
<int>-1059162278</int> 
<int>-489792147</int> 
<int>971228309</int> 
<int>1326244365</int> 
</IntArray> 
</ForSerialization>

Как видно, здесь содержатся данные об объекте ForSerialization, которые позволят восстановить его, то есть – десериализовать. После вывода сообщения, имея поток, который содержит сериализованные данные, мы создаём десериализатор. Это – так же объект XmlSerizlizer, при его создании указывается тип данных, с которыми мы хотим работать. При создании объекта на основе сериализованных данных, мы вызываем метод Deserialize объекта XmlSerializer, приводя полученный объект к нужному типу. Для того, чтобы проконтролировать правильность создания объекта, можно установить точку останова на строку, которая выводит сообщение об успешной десериализации и просмотреть в отладчике полученный объект, сравнив его с исходным объектом, который мы сериализовали.

В обработчике события нажатия на кнопку "Сериализация, JSON", мы выполняем ту же последовательность действий, которую выполняли для XML, но – для формата JSON. Для сериализации используем объект типа DataContractJsonSerizlizer, при его создании так же нужно указать тип объекта, который мы собираемся сериализовать. Подготовим поток в памяти, который примет сериализованные данные и, командой WriteObject, сериализуем объект. Дальнейшие действия схожи с вышеописанным для XML, мы получаем из потока строку и выводим в сообщении. Вот как выглядит это сообщение, содержащее данные объекта, сериализованного в JSON:

{"IntArray":[1394960975,-1568024929,-1589055262,1970233772,-819919232,
-1407633318,125844691,1787338925,-643262746,-232092512],
"Line1":"Пример строки","Number1":123}

На примере данных, полученных в результате сериализации объектов с использованием форматов JSON и XML хорошо видна разница между ними, о которой мы упоминали выше. А именно, при представлении данных в формате JSON для их хранения и передачи потребуется меньше ресурсов (для более сложных объектов эта разница еще существеннее), чем при использовании XML. В то же время, XML-код легче воспринимать. Опять же, особенно хорошо это заметно при работе с более крупными объектами. При передаче данных по сети, в ходе взаимодействия с каким-либо сервисом, использование JSON, при прочих равных условиях, даст более высокую скорость обмена данными, приведет к экономии сетевого трафика. Если подсчитать количество символов, которое занимают XML и JSON-код (нас интересуют скорее не сами цифры, так как мы не учитываем здесь кодировку, в которой будут сохранены эти данные, не учитываем возможность их сжатия, а соотношение), то окажется, что JSON-представление данных занимает 164 символа, XML-представление – 474. То есть, XML-данные, содержащие тот же объем полезной информации, в нашем случае, примерно в 2,8 раза больше.

Продолжая пример работы с JSON, мы, используя уже имеющийся поток, хранящий сериализованные данные, десериализуем их, создавая на их основе новый объект, пользуясь методом ReadObject объекта типа DataContractJsonSeriаlizer.

Принимая решение об использовании того или иного способа сериализации данных и работы с такими данными (например, в XML или JSON могут поступать ответы веб-службы на посылаемые ей запросы), следует рассмотреть возможность использования альтернативных библиотек, реализующих эти возможности. Сериализация и десериализация способна создать некоторую нагрузку на систему (а при работе с большими объемами данных, получаемыми, например, от веб-службы – нагрузку довольно ощутимую), поэтому оптимизации этого процесса стоит уделить внимание. Ответ на вопрос о целесообразности использования того или иного формата не так очевиден, как может показаться на первый взгляд. Дело в том, что работа с XML-данными и JSON-данными требует различных вычислительных ресурсов. Скорость её выполнения зависит от данных, с которыми осуществляется работа, от используемых библиотек для сериализации и десериализации, от других факторов. Всё это говорит в пользу проведения предварительных испытаний каждой из этих технологий при работе с конкретной службой (возможно, конечно, что выбор будет сделан в пользу какой-нибудь другой технологии передачи и хранения данных) и сравнения результатов таких испытаний.

Обработчик нажатия на кнопку Сжатие данных демонстрирует работу с библиотекой Zlib, в частности, её методы CompressString и UncompressString. Мы используем здесь строковую переменную, которая содержит некоторый текст. Мы можем передать эту строку методу CompressString, но он возвращает результаты сжатия в байтовый массив (эта библиотека поддерживает и работу с потоками). Этот байтовый массив мы передаем методу UncompressString – он возвращает данные в строку. Предварительно, для оценки уровня сжатия, который был достигнут при работе с нашими данными, мы записываем исходную строку в байтовый массив BytesFromString, для того, чтобы показать размер этого массива и сравнить его с массивом, хранящий сжатое представление данных. В нашем случае массив, хранящий исходную строку, содержит 104 байта, массив, хранящий те же данные в сжатом виде – 64 байта.

Выводы

Работа с JSON, XML и другими форматами данных требуется как при создании приложений, рассчитанных на локальное использование, так и при создании сетевых приложений, обрабатывающих ответы служб, получаемые в различных форматах. Правильный выбор формата передачи данных позволяет создать приложение, которое более эффективно использует системные ресурсы. Сжатие данных – это очень важная технология, которая позволяет экономить место – как на устройствах хранения данных, так и при передаче данных по сети. Однако, её использование подразумевает некоторые затраты вычислительных ресурсов. Всё это говорит в пользу тщательного подхода к выбору технологий, которые будут применяться для создания того или иного приложения.

Задание

Подумайте, как ваше приложение может воспользоваться возможностями сериализации и десериализации в организации его работы. Оцените возможную выгоду от использования возможностей сжатия данных при организации хранения данных вашего приложения. На основе примера, приведенного в лабораторной работе, создайте приложение, которое позволяет оценить скорость сериализации объекта, объем данных которого можно регулировать в диапазоне 10 – 50 Мб, и десериализации данных в такой объект. Используйте в эксперименте форматы JSON и XML Для оценки времени можно воспользоваться возможностями получения текущего времени в начале и в конце операции. Подготовьте отчет о проведенной работе.

Дополнительные материалы

К данной лекции подготовлено видеоприложение и демонстрационный программный проект.

Страницы:

Цель работы: освоить технологию работы с форматами JSON и XML и работу со сжатием данных

JSON, XML, сжатие данных

Данные, которые передаются между веб-сервисом и клиентским приложением, кодируют с использованием определенных форматов. Существует множество таких форматов. Например, в ответ на запрос загрузки веб-страницы с веб-сервера могут поступить данные в формате HTML. При работе с API веб-сервисов обычно используются другие форматы, среди них наиболее распространены JSON (Java Script Object Notation) и XML (eXtensible Markup Language). Эти форматы могут использоваться и в задачах, которые не связаны с веб-службами. Например, в XML или JSON могут быть сериализованы объекты (при условии возможности сериализации), состояние которых нужно сохранить в постоянной памяти и загрузить, десериализовав, при очередном запуске приложения.

Как мы увидим ниже, JSON и XML имеют определенные особенности, которые можно учитывать, принимая решение об использовании того или иного формата. С их помощью можно закодировать одни и те же данные, существенная разница между ними будет заключаться в размере полученных данных и в удобстве восприятия данных человеком (нужно обычно при отладке). Ниже мы рассмотрим эти характеристики на практике.

С вопросами передачи и хранения данных тесно связана тема сжатия данных. Сжатие позволяет особым образом обработать данные, получив их представление, имеющее меньший размер, чем исходные данные, но содержащее ту же информацию. В данном случае речь идёт о так называемом сжатии информации без потерь, такое сжатие применимо, например, к документам (или к любым другим данным), когда критически важно точное соответствие данных, хранящихся в исходном документе тем данным, которые получены из сжатой копии документа. Среди алгоритмов сжатия без потерь можно отметить, например, алгоритм .ZIP.

Существует и так называемое сжатие с потерями – оно используется в тех случаях, когда отбрасывание некоторой части информации не ухудшает (или ухудшает незначительно) возможности по работе с информацией. Взамен потери некоторой части информации мы получаем очень большие уровни сжатия. Такое сжатие используется для кодирования изображений (.JPG), звуковых файлов (.MP3), видеофайлов.

Работа с JSON, XML, сжатие данных

Создадим учебное приложение (P7_1), которое демонстрирует работу с JSON, XML и основы работы со сжатыми данными. Воспользуемся шаблоном Приложение Windows Phone. Добавим в приложение новый класс, назовём его ForSerialization и опишем в нём следующие поля и конструктор (Листинг 27.1.)

using System;

namespace P7_1
{
    public class ForSerialization
    {
        //Открытые поля
        public string Line1;
        public int Number1;

        public int[] IntArray;

        public ForSerialization()
        {
            //Инициализация полей
            Line1 = "Пример строки";
            Number1 = 123;

            IntArray = new int[10];

            Random r = new Random();

            for (int i = 0; i < 10; i++)
            {
                IntArray[i] = r.Next() - r.Next();
            }
        }
    }
}

Класс объявлен как общедоступный, это нужно для сериализации, в нём объявлено несколько открытых полей, одно из которых – строка, другое – число, третье поле – это массив, в который мы добавляем десять случайных чисел в конструкторе класса, там же мы инициализируем два других поля.

На главной странице приложения, рис. 27.1., разместим три кнопки. Мы будем размещать код, демонстрирующий интересующие нас техники работы, в обработчиках их событий Click.

(рис 27.1) Страница MainPage

Кроме того, обратите внимание на состав папки References проекта. Здесь мы используем библиотеку Ionic.Zlib для демонстрации работы со сжатыми данными. Существуют и другие библиотеки, подходящие для тех же целей.

В Листинге 27.2 приведен полный код файла MainPage.xaml.cs

using Ionic.Zlib;
using Microsoft.Phone.Controls;
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Windows;
using System.Xml.Serialization;

namespace P7_1
{

    public partial class MainPage : PhoneApplicationPage
    {
        // Конструктор
        public MainPage()
        {
            InitializeComponent();
        }

        private void cmd_SerializationXML_Click(object sender, RoutedEventArgs e)
        {
            //Объект для сериализации
            ForSerialization ObjectForSerialization = new ForSerialization();

            //Тип данных для сериализации

            Type t = typeof(ForSerialization);

            //XML-сериализатор для объекта
            XmlSerializer XmlS = new XmlSerializer(t);

            //Поток для хранения результатов сериализации
            MemoryStream XmlStr = new MemoryStream();

            //Сериализация в поток
            XmlS.Serialize(XmlStr, ObjectForSerialization);

            //Подготовка к чтению данных из потока
            XmlStr.Position = 0;

            //Средство считывания потока
            StreamReader StRead = new StreamReader(XmlStr);

            //Строка в которую считывается поток
            string XmlString = StRead.ReadToEnd();

            //Вывод строки
            MessageBox.Show(XmlString);

            //Десериализация

            XmlSerializer XmlDS = new XmlSerializer(t);

            //Подготовка потока
            XmlStr.Position = 0;

            //Создаём объект из сериализованных данных
            ForSerialization NewObjectFromXML = XmlDS.Deserialize(XmlStr) as ForSerialization;

            MessageBox.Show("Десериализация завершена");

        }

        private void cmd_SerializationJSON_Click(object sender, RoutedEventArgs e)
        {
            //Объект для сериализации
            ForSerialization ObjectForSerialization = new ForSerialization();

            //Тип данных для сериализации

            Type t = typeof(ForSerialization);

            //JSON-сериализатор
            DataContractJsonSerializer JsS = new DataContractJsonSerializer(t);

            //Поток для хранения результатов сериализации
            MemoryStream JsonStr = new MemoryStream();

            JsS.WriteObject(JsonStr, ObjectForSerialization);

            //Подготовка к чтению данных из потока
            JsonStr.Position = 0;

            //Средство считывания потока
            StreamReader StRead = new StreamReader(JsonStr);

            //Строка в которую считывается поток
            string JsonString = StRead.ReadToEnd();

            //Вывод строки
            MessageBox.Show(JsonString);

            //Десериализация

            DataContractJsonSerializer JsDS = new DataContractJsonSerializer(t);

            //Подготовка потока
            JsonStr.Position = 0;

            //Создаём объект из сериализованных данных
            ForSerialization NewObjectFromJSON = JsDS.ReadObject(JsonStr) as ForSerialization;

            MessageBox.Show("Десериализация завершена");


        }

        private void cmd_Compression_Click(object sender, RoutedEventArgs e)
        {
            string DataForCompression = "Данные для сжатия 1 Данные для сжатия 
2 Данные для сжатия 3";
            //Строка для сжатия, записанная в массив байтов
            Byte[] BytesFromString = System.Text.Encoding.UTF8.GetBytes(DataForCompression);

            //Новый массив, содержащий сжатую строку
            byte[] CompressedData = GZipStream.CompressString(DataForCompression);
            //Строка, восстановленная из сжатых данных
            string Uncompressed = GZipStream.UncompressString(CompressedData);

            MessageBox.Show("Размеры байтовых массивов. Для исходной строки: " + BytesFromString.Length.ToString() + " байт. 
При сжатии: " + CompressedData.Length.ToString() + " байт");
            MessageBox.Show("Исходная строка: (" + DataForCompression + "), строка, 
полученная после сжатия и распаковки: (" + Uncompressed + ").");
        }
    }
}

Обратите внимание на состав директив using. Нам, для работы с рассматриваемыми возможностями, понадобилось подключить некоторые пространства имен, которые, по умолчанию, не подключены.

Рассмотрим код метода cmd_SerializationXML_Click, обработчика события нажатия на кнопку "Сериализация, XML".

Здесь мы сначала создаём объект типа ForSerialization. После создания в конструкторе производится его инициализация, он готов к дальнейшим исследованиям.

В переменную типа Type запишем тип данных объекта – эта переменная понадобится нам при настройке сериализатора. Конечно, необязательно создавать отдельную переменную, тип объекта для сериализации можно получить и в конструкторе сериализатора. Сериализатор – объект типа XmlSerizlizer, создаётся с указанием типа данных, которые мы собираемся сериализовать.

Следующим шагом является создание потока, в данном случае это поток типа MemoryStream, в который мы собираемся записывать сериализованные данные. В качестве потоков могут выступать и другие потоки. Например, те, которые соответствуют открытым файлам.

Метод Serialize объекта типа XmlSerizlizer, выполняет сериализацию. При его вызове указывается, во-первых, поток, в который нужно записать сериализованные данные, во-вторых – объект, который следует сериализовать. После выполнения сериализации наш поток содержит XML-представление объекта, мы можем, при практическом использовании данного механизма, отправить это представление по сети, сохранить на диск. Сейчас мы хотим получить строковое представление потока для того, чтобы просмотреть его. Для этого мы сначала устанавливаем указатель потока на его первую позицию, затем создаём объект типа StreamReader, с помощью которого можно прочитать поток. Мы будем читать его в строку XmlString и выводить на экран в виде сообщения, которое можно прочитать. Это сообщение будет содержать следующий текст:

<?xml version="1.0" encoding="utf-8" ?> 
- <ForSerialization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<Line1>Пример строки</Line1> 
<Number1>123</Number1> 
- <IntArray> 
<int>-518451200</int> 
<int>-463632356</int> 
<int>1312024067</int> 
<int>689675499</int> 
<int>-43902912</int> 
<int>-202627666</int> 
<int>-1059162278</int> 
<int>-489792147</int> 
<int>971228309</int> 
<int>1326244365</int> 
</IntArray> 
</ForSerialization>

Как видно, здесь содержатся данные об объекте ForSerialization, которые позволят восстановить его, то есть – десериализовать. После вывода сообщения, имея поток, который содержит сериализованные данные, мы создаём десериализатор. Это – так же объект XmlSerizlizer, при его создании указывается тип данных, с которыми мы хотим работать. При создании объекта на основе сериализованных данных, мы вызываем метод Deserialize объекта XmlSerializer, приводя полученный объект к нужному типу. Для того, чтобы проконтролировать правильность создания объекта, можно установить точку останова на строку, которая выводит сообщение об успешной десериализации и просмотреть в отладчике полученный объект, сравнив его с исходным объектом, который мы сериализовали.

В обработчике события нажатия на кнопку "Сериализация, JSON", мы выполняем ту же последовательность действий, которую выполняли для XML, но – для формата JSON. Для сериализации используем объект типа DataContractJsonSerizlizer, при его создании так же нужно указать тип объекта, который мы собираемся сериализовать. Подготовим поток в памяти, который примет сериализованные данные и, командой WriteObject, сериализуем объект. Дальнейшие действия схожи с вышеописанным для XML, мы получаем из потока строку и выводим в сообщении. Вот как выглядит это сообщение, содержащее данные объекта, сериализованного в JSON:

{"IntArray":[1394960975,-1568024929,-1589055262,1970233772,-819919232,
-1407633318,125844691,1787338925,-643262746,-232092512],
"Line1":"Пример строки","Number1":123}

На примере данных, полученных в результате сериализации объектов с использованием форматов JSON и XML хорошо видна разница между ними, о которой мы упоминали выше. А именно, при представлении данных в формате JSON для их хранения и передачи потребуется меньше ресурсов (для более сложных объектов эта разница еще существеннее), чем при использовании XML. В то же время, XML-код легче воспринимать. Опять же, особенно хорошо это заметно при работе с более крупными объектами. При передаче данных по сети, в ходе взаимодействия с каким-либо сервисом, использование JSON, при прочих равных условиях, даст более высокую скорость обмена данными, приведет к экономии сетевого трафика. Если подсчитать количество символов, которое занимают XML и JSON-код (нас интересуют скорее не сами цифры, так как мы не учитываем здесь кодировку, в которой будут сохранены эти данные, не учитываем возможность их сжатия, а соотношение), то окажется, что JSON-представление данных занимает 164 символа, XML-представление – 474. То есть, XML-данные, содержащие тот же объем полезной информации, в нашем случае, примерно в 2,8 раза больше.

Продолжая пример работы с JSON, мы, используя уже имеющийся поток, хранящий сериализованные данные, десериализуем их, создавая на их основе новый объект, пользуясь методом ReadObject объекта типа DataContractJsonSeriаlizer.

Принимая решение об использовании того или иного способа сериализации данных и работы с такими данными (например, в XML или JSON могут поступать ответы веб-службы на посылаемые ей запросы), следует рассмотреть возможность использования альтернативных библиотек, реализующих эти возможности. Сериализация и десериализация способна создать некоторую нагрузку на систему (а при работе с большими объемами данных, получаемыми, например, от веб-службы – нагрузку довольно ощутимую), поэтому оптимизации этого процесса стоит уделить внимание. Ответ на вопрос о целесообразности использования того или иного формата не так очевиден, как может показаться на первый взгляд. Дело в том, что работа с XML-данными и JSON-данными требует различных вычислительных ресурсов. Скорость её выполнения зависит от данных, с которыми осуществляется работа, от используемых библиотек для сериализации и десериализации, от других факторов. Всё это говорит в пользу проведения предварительных испытаний каждой из этих технологий при работе с конкретной службой (возможно, конечно, что выбор будет сделан в пользу какой-нибудь другой технологии передачи и хранения данных) и сравнения результатов таких испытаний.

Обработчик нажатия на кнопку Сжатие данных демонстрирует работу с библиотекой Zlib, в частности, её методы CompressString и UncompressString. Мы используем здесь строковую переменную, которая содержит некоторый текст. Мы можем передать эту строку методу CompressString, но он возвращает результаты сжатия в байтовый массив (эта библиотека поддерживает и работу с потоками). Этот байтовый массив мы передаем методу UncompressString – он возвращает данные в строку. Предварительно, для оценки уровня сжатия, который был достигнут при работе с нашими данными, мы записываем исходную строку в байтовый массив BytesFromString, для того, чтобы показать размер этого массива и сравнить его с массивом, хранящий сжатое представление данных. В нашем случае массив, хранящий исходную строку, содержит 104 байта, массив, хранящий те же данные в сжатом виде – 64 байта.

Выводы

Работа с JSON, XML и другими форматами данных требуется как при создании приложений, рассчитанных на локальное использование, так и при создании сетевых приложений, обрабатывающих ответы служб, получаемые в различных форматах. Правильный выбор формата передачи данных позволяет создать приложение, которое более эффективно использует системные ресурсы. Сжатие данных – это очень важная технология, которая позволяет экономить место – как на устройствах хранения данных, так и при передаче данных по сети. Однако, её использование подразумевает некоторые затраты вычислительных ресурсов. Всё это говорит в пользу тщательного подхода к выбору технологий, которые будут применяться для создания того или иного приложения.

Задание

Подумайте, как ваше приложение может воспользоваться возможностями сериализации и десериализации в организации его работы. Оцените возможную выгоду от использования возможностей сжатия данных при организации хранения данных вашего приложения. На основе примера, приведенного в лабораторной работе, создайте приложение, которое позволяет оценить скорость сериализации объекта, объем данных которого можно регулировать в диапазоне 10 – 50 Мб, и десериализации данных в такой объект. Используйте в эксперименте форматы JSON и XML Для оценки времени можно воспользоваться возможностями получения текущего времени в начале и в конце операции. Подготовьте отчет о проведенной работе.

Дополнительные материалы

К данной лекции подготовлено видеоприложение и демонстрационный программный проект.

Вернуться к учебному плану