Краткий экскурс
Фактически каждый программист рано (или поздно) сталкивается с сериализацией.
Сериализация — это процесс перевода структуры данных в последовательность битов, или же в другую структуру данных, которую удобно хранить, передавать.
Десериализация — это обратный процесс. Процесс преобразования сериализованных данных в структуру данных.
Подобные вещи часто встречаются при обмене данными между клиентом и сервером, между двумя клиентами (P2P). В общем много где встречается. Моё первое знакомство было при работе с API одного из российских сервисов.
API — это Application Programming Interface. То есть прослойка между функциональной частью какого-либо программного обеспечения и вашего программного обеспечения.
Например — Вам хочется написать программу, которая будет отображать погоду в Москве. Вам не хочется устанавливать свои метеодатчики и другое оборудование.
Допустим, что есть сервис «Погода в России», который имеет свой API. И данный сервис на бесплатно (или же платно) дает доступ к нему вашим приложениям. Конечно — всегда можно написать парсер нужной страницы и выводить информацию. Но любые изменения в содержимом страницы могут привести к тому, что парсер придется тоже обновлять.
Глупо говорить о преимуществах API по сравнению с парсингом. Это скорость, удобство работы, а также, очень часто, более расширенный функционал.
Так что если сервис предлагает API — глупо отказываться.
Update 08.07.2019
Важный момент.
Класс, который Вы хотите сериализовать/десериализовать, должен соответствовать некоторым требованиям, чтобы не было проблем при работе с ним:
- У класса должен быть обязательно объявлен конструктор без параметров, или не объявлено конструкторов вовсе;
- Лучше использовать свойства, а не поля (с {get; и set;} как в примерах выше;
- Если у свойства отсутствует get’тер, или set’тер — то будьте готовы к тому, что часть функционала JSON-сериализатора будет работать не верно. Например:
- У вас отсутствует публичный GET’тер, но есть SET’тер. Тогда вы сможете десериализовать (JSON в объект) свойство объекта, но сериализовать (объект в JSON) его вы не сможете;
- У вас отсутствует публичный SET’тер, но есть GET’тер. Тогда вы не сможете десериализовать (JSON в объект) свойство объекта, но сможете его сериализовать (объект в JSON);
 
Функции преобразования и восстановления при сериализации
Не всегда сериализация может быть выполнена полностью автоматически. В жизни встречаются самые разные ситуации. Поэтому мы добавили возможность использовать «самописную» функцию обработки значений при записи в JSON и при чтении из JSON.
В методе ЗаписатьJSON() она называется Функция преобразования и описывается с помощью трёх параметров:
- ИмяФункцииПреобразования;
- МодульФункцииПреобразования;
- ДополнительныеПараметрыФункцииПреобразования.
В методе ПрочитатьJSON() она называется Функция восстановления и для неё есть аналогичные параметры:
- ИмяФункцииВосстановления;
- МодульФункцииВосстановления;
- ДополнительныеПараметрыФункцииВосстановления.
При записи в JSON эта функция полезна потому, что позволяет самостоятельно преобразовать в JSON те типы, которые не подлежат автоматическому преобразованию. Или даже совсем отказаться от их сериализации.
Например, так оказалось, что в записываемой структуре одно из значений — это ссылка на элемент справочника ПодразделенияОрганизаций. Такое значение (ссылка на объект 1С:Предприятия) не может быть автоматически сериализовано средствами платформы. Тогда, используя функцию преобразования, мы можем получить для этого значения его строковое представление в удобном виде. Например, в виде строки «ИП Петров: Отдел рекламы».
Результат выполнения примера:
{
	"Фамилия": "Иванов",
	"Имя": "Иван",
	"Отчество": "Иванович",
	"Подразделение": "ИП Петров: Отдел рекламы",
	"Телефоны": 
}
При чтении из JSON функция восстановления может использоваться для того, чтобы преобразовать данные JSON в типы 1С, которые не могут являться результатом автоматического преобразования, или для того, чтобы самостоятельно (не автоматически) преобразовать даты JSON в даты 1С:Предприятия.
Десериализация
Теперь нужно эту строку десериализовать обратно в класс. Для этого, естественно, должен быть объявлен соответствующий класс, иначе программа не сможет ничего десериализовать.
Сам код десериализации следующий:
C#
string json = richTextBox.Text;
MyMusic newMusic = JsonConvert.DeserializeObject<MyMusic>(json);
| 1 | stringjson=richTextBox.Text; MyMusic newMusic=JsonConvert.DeserializeObject<MyMusic>(json); | 
Теперь выведем на экран содержимое десериализованного JSON’а:
На экран должно вывестись следующий текст:
Как видите — с JSON очень удобно работать. Но есть одна маленькая хитрость, которая сильно упростит вашу жизнь при десериализации. Чтобы вам вручную не создавать огромные классы анализируя пример JSON’а, который вам возвращает API — можно его сгенерировать автоматически. В этом вам поможет сайт Json2CSharp. Просто вставьте в него строку с JSON, которую вы получили из API и он сгенерирует вам необходимые классы. Основной класс будет всегда RootObject (в примере был MyMusic), но никто не мешает вам его переименовать в нужный.
Пароль к архиву: котодомик.рф
Сериализация примитивных типов и коллекций в JSON
Вторая группа средств работы с JSON хороша тем, что избавляет вас от рутинной работы по чтению/записи каждого отдельного значения или свойства. При чтении документы JSON отображаются в фиксированный набор типов платформы: Строка, Число, Булево, Неопределено, Массив, ФиксированныйМассив, Структура, ФиксированнаяСтруктура, Соответствие, Дата. Соответственно, в обратную сторону, композиция объектов этих типов позволяет сформировать в памяти и быстро записать в файл структуру JSON. Таким образом, чтение и запись небольшого объема JSON заранее известной структуры можно производить немногими строчками кода.
Основное назначение этих средств мы видим в обмене информацией с внешними системами, чтении конфигурационных файлов в формате JSON.
Сериализацию вы можете выполнять с помощью методов глобального контекста ПрочитатьJSON() и ЗаписатьJSON(). Они работают в связке с объектами ЧтениеJSON и ЗаписьJSON.
В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:
Код 1С:Предприятия, выполняющий десериализацию, может выглядеть следующим образом:
А пример сериализации (записи) в JSON может выглядеть так:
Результат записи:
{
	"Фамилия": "Иванов",
	"Имя": "Иван",
	"Отчество": "Иванович",
	"Возраст": 40,
	"Женат": true,
	"Телефоны": 
}
Использование JSON в HTTP интерфейсах приложений
Автоматически генерируемый REST интерфейс прикладных решений
При обращении к REST интерфейсу прикладного решения вы можете получать ответ в формате JSON. Для этого в адресной строке вам нужно указать параметр $format=json. Либо указать MIME тип «application/json» в заголовке Accept HTTP запроса. Например:
Запрос:
GET /TestInfobase/odata/standard.odata/СправочникДляТестов?$format=json HTTP/1.1 MaxDataServiceVersion: 3.0;NetFx Accept: application/json Accept-Charset: UTF-8 User-Agent: Microsoft ADO.NET Data Services
Ответ:
HTTP/1.1 200 OK
Content-Length: 9429
Content-Type: application/json;charset=utf-8
Server: Microsoft-IIS/7.5
DataServiceVersion: 3.0
X-Powered-By: ASP.NET
Date: Mon, 12 Aug 2013 09:44:07 GMT
    
{
"odata.metadata":"http://host/svc/$metadata#СправочникДляТестов",
"value":[
{
	"Ref_Key":guid'cc6a7df3-8cfe-11dc-8ca0-000d8843cd1b',
	"DataVersion":"AAAAAQAAAAE",	
	"DeletionMark":false,
	"Parent_Key":guid'bbb079ae-8c51-11db-a9b0-00055d49b45e',
	"IsFolder":false,
	"Code":000000025,
	"Description":"Пинетки",
	"Поставщик_Key":guid'd1cb82a7-8e8b-11db-a9b0-00055d49b45e',
	"Поставщик@navigationLinkUrl":"СправочникДляТестов(guid'cc6a7df3-8cfe-11dc-8ca0-000d8843cd1b')/Поставщик",
	"РеквизитХранилище_Type": "image/jpeg",
	"РеквизитХранилище_Base64Data@mediaReadLink": "Catalog_ДемоСправочник(guid'cf2b1a24-1b96-11e3-8f11-5404a6a68c42')/РеквизитХранилище_Base64Data",
	"РеквизитХранилище_Base64Data": <строка с закодированными данными>
	…
},
{…},
{…}
]
}
Вы можете управлять объёмом передаваемой информации за счёт изменения детальности представления метаданных в выгрузке. Существуют три уровня: Nometadata, Minimalmetadata и Fullmetadata. По-умолчанию (на примере вверху) используется средний уровень — Minimalmetadata. На уровне Nometadata объём передаваемой информации минимальный, а на уровне Fullmetadata — максимальный. Однако при этом нужно понимать, что сокращение объёма передаваемой информации приводит к более интенсивным вычислениям на клиенте. И наоборот, когда вся информация включается в выгрузку, объём вычислений на клиенте будет минимальным.
Детальность представления метаданных вы можете указать, например, в адресной строке.
Сведения о метаданных не передаются:
GET /TestInfobase/odata/standard.odata/СправочникДляТестов/?$format=application/json;odata= minimalmetadata
Вся информация о метаданных включается в выгрузку:
GET /TestInfobase/odata/standard.odata/СправочникДляТестов/?$format=application/json;odata=fullmetadata
HTTP-сервисы прикладного решения
HTTP-сервисы, реализованные в прикладном решении, также могут возвращать ответ в формате JSON. Для этого вам проще всего сформировать тело ответа в JSON, получить его как строку, а затем установить из этой строки тело HTTP ответа сервиса. При этом желательно указать, что BOM (Byte Order Mark, метка порядка байтов) использоваться не должна.
Последний параметр (ИспользованиеByteOrderMark.НеИспользовать) вы можете и не указывать, если режим совместимости конфигурации не установлен, или он больше чем Версия8_3_5. Потому что в этом случае BOM автоматически будет использоваться только для кодировок UTF-16 и UTF-32, а для UTF-8, UTF-16LE/UTF-16BE, UTF-32LE/UTF-32BE и других она использоваться не будет.
Взаимодействие со сторонними HTTP сервисами
При взаимодействии со сторонними HTTP интерфейсами у вас также может возникнуть необходимость формирования запросов к ним в формате JSON. В этом случае алгоритм ваших действий будет аналогичным. Формируете тело запроса в JSON. Получаете тело в виде строки. Из этой строки устанавливаете тело HTTP запроса. BOM не используете.
Дальнейшее развитие
Мы думаем над тем, чтобы предоставить вам возможность сериализации в JSON прикладных типов 1С:Предприятия: ссылок, объектов, наборов записей и т.д. Поэтому есть вероятность появления ещё одного, третьего уровня средств работы с JSON. Этот уровень позволит вам преобразовывать в JSON любые типы 1С:Предприятия, для которых поддерживается XDTO-сериализация в XML.
Сериализация типа Дата
Данные типа Дата сериализуются в JSON автоматически, а вот обратное преобразование (десериализация) может быть выполнено не всегда. JSON не содержит типа Дата, значения даты представляются в нём строкой. Конечно, существуют некоторые форматы представления дат, но вообще говоря, внешний вид такой строки может быть самым разнообразным.
Для сериализации типа Дата в JSON у метода ЗаписатьJSON() вы можете использовать параметр НастройкиСериализации. Это объект встроенного языка, который позволяет указать, в каком варианте будет записана дата (UTC, локальная дата или локальная дата со смещением) и в каком формате (ISO, JavaScript или Microsoft).
Код 1С:Предприятия:
Текст JSON:
При чтении даты из JSON всё обстоит сложнее. В параметре ИменаСвойствСоЗначениямиДата вы можете перечислить те свойства JSON, значения которых нужно преобразовать в дату 1С:Предприятия (тип Дата). А в параметре ОжидаемыйФорматДаты вам нужно указать, в каком формате эти данные содержатся в JSON (ISO, JavaScript или Microsoft).
Текст JSON:
Код 1С:Предприятия:
Однако если окажется, что в какой-то момент формат данных JSON не совпадает с ожидаемым форматом, будет вызвано исключение.
В такой ситуации, для большей универсальности, вы можете включить те же самые свойства JSON в массив, подлежащий обработке функцией восстановления — ИменаСвойствДляОбработкиВосстановления. И уже в функции восстановления вы самостоятельно десериализуете даты JSON, в каком бы формате они ни были представлены.
Сериализация
В данном примере мы рассмотрим библиотеку «Newtonsoft.Json» для работы с JSON. Почему её? Потому что она удобная.
Для начала её нужно добавить в references.
Для этого нужно нажать ПКМ на References и выбрать «Добавить ссылку…».
Тут можно найти его в поиске (если уже использовали), скачать его через NuGet, или же просто добавить как обычную библиотеку через «Обзор».
На всякий случай оставлю библиотеку тут: скачать Newtonsoft.Json.dll.
Теперь можно приступить к коду.
Для начала нужно добавить NameSpace библиотеки в код. Для этого добавим в using следующую строку:
C#
using System;
// Далее ваши библиотеки
using Newtonsoft.Json;
| 1 | usingSystem; // Далее ваши библиотеки usingNewtonsoft.Json; | 
Теперь нужно описать класс, который будем сериализовать и десериализовать:
C#
class MyMusic
        {
            public Track[] Tracks { get; set; }
        }
        class Track
        {
            public string Artist { get; set; }
            public string Album { get; set; }
            public string Title { get; set; }
            public string Year { get; set; }
}
| 1 | classMyMusic { publicTrackTracks{get;set;} } classTrack { publicstringArtist{get;set;} publicstringAlbum{get;set;} publicstringTitle{get;set;} publicstringYear{get;set;} } | 
Будем считать, что пишем программу для ведения учета домашней музыкальной коллекции. Базовый класс — MyMusic, вспомогательный класс — Track.
Теперь добавим несколько треков:
C#
MyMusic myCollection = new MyMusic();
            myCollection.Tracks = new Track;
            myCollection.Tracks = new Track()
            {
                Artist=»Artist1″,
                Album=»Album1″,
                Title=»Title1″,
                Year=»2015″
            };
            myCollection.Tracks = new Track()
            {
                Artist = «Artist2»,
                Album = «Album2»,
                Title = «Title2»,
                Year = «2015»
            };
            myCollection.Tracks = new Track()
            {
                Artist = «Artist3»,
                Album = «Album3»,
                Title = «Title3»,
                Year = «2015»
            };
| 1 | MyMusic myCollection=newMyMusic(); myCollection.Tracks=newTrack3; myCollection.Tracks=newTrack() { Artist=»Artist1″, Album=»Album1″, Title=»Title1″, Year=»2015″ }; myCollection.Tracks1=newTrack() { Artist=»Artist2″, Album=»Album2″, Title=»Title2″, Year=»2015″ }; myCollection.Tracks2=newTrack() { Artist=»Artist3″, Album=»Album3″, Title=»Title3″, Year=»2015″ }; | 
Теперь сериализуем этот класс и выведем на RichTextBox:
C#
string serialized = JsonConvert.SerializeObject(myCollection);
richTextBox.Text = serialized;
| 1 | stringserialized=JsonConvert.SerializeObject(myCollection); richTextBox.Text=serialized; | 
В результате чего мы должны получить такую строку на выходе:
{«Tracks»:}
| 1 | {«Tracks»{«Artist»»Artist1″,»Album»»Album1″,»Title»»Title1″,»Year»»2015»},{«Artist»»Artist2″,»Album»»Album2″,»Title»»Title2″,»Year»»2015»},{«Artist»»Artist3″,»Album»»Album3″,»Title»»Title3″,»Year»»2015»}} | 





























