Что такое схема данных, зачем она нужна, какие форматы файлов предусматривают наличие схемы и как это связано с сериализацией. Смотрим на примере JSON, XML, YAML и Protobuf.
Как связаны форматы и схемы данных и при чем здесь сериализация
При разработке требований к ПО или в рамках проектов интеграции информационных систем у аналитика возникают вопросы про схему данных и формат файлов. Это связанные понятия, однако не одно и тоже. Формат файла, отображаемый в его расширении, говорит о том, каким образом сообщение сериализуется, т.е. переводится в двоичный код, последовательность битов из 1 и 0, для передачи по сети или сохранения в постоянной памяти (на диске). Обратный процесс восстановления сообщения, имеющего практический смысл, из битовой последовательности, называется десериализацией.
За сериализацию и десериализацию отвечают приложения-источники и приемники сообщений, реализуя программный код работы с объектами и структурами данных. Этот код выполняет нужное преобразование данных каждого типа (числовые, символьные, дата и время, логические и пр.), которые встречаются в сообщении. На практике разработчик не часто пишет собственные сериализаторы и десериализаторы, а, в основном, пользуется готовыми библиотеками или встроенными во фреймворк классами.
Таким образом, формат файла описывает правила сериализации данных, которые есть в сообщении. Однако, этого недостаточно для верификации сообщения, пришедшего в систему-приемник из системы-источника. Например, необходимо проверить, что пришли все нужные данные, и их тип соответствует ожидаемому. За это отвечает схема данных, которая задает структуру сообщения: набор полей и их типы данных, а также обязательность каждого поля. В зависимости от используемого формата сериализации, схема данных может быть встроена в само сообщения или представлена отдельным файлом. Например, бинарный формат Protobuf, который используется в технологии gRPC, включает описание схемы в само сообщение, а JSON, XML и YAML предполагают описание схемы в отдельном файле аналогичных форматов.
Чтобы стало понятнее, далее посмотрим пример представления одного и того же по смыслу сообщения в разных форматах (JSON, XML, YAML и Protobuf), а также сгенерируем схему для них.
Основы архитектуры и интеграции информационных систем
Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.
Представление сообщений в форматах JSON, XML, YAML и Protobuf со схемами данных
В качестве примера возьмем ранее рассмотренные в этой статье данные по клиентским заявкам. Сперва представим их в формате JSON как массив объектов, заключив в квадратные скобки.
{ "apps": [ { "course": "TTIS", "name": "Анна", "email": "anna@email.ru", "phone": "123456789", "corp": true, "wishes": { "city": "Казань", "online": true, "group ": true, "number_of_students": 20 } }, { "course": "MODP", "name": "Борис", "email": "boris@email.ru", "corp": false, "wishes": { "online": true, "group ": false } }, { "course": "OAIS", "name": "Лиза", "phone": "987654321", "corp": false, "wishes": { "country": "Россия", "online": true, "group ": true, "info": "Прошу связаться со мной в телеграм" } }, { "course": "BAMP", "name": "Никита", "phone": "1122334455", "email": "nikita@email.bank", "corp": true, "wishes": { "country": "Казахстан", "city": "Астана", "online": false, "group ": true, "company": "Банк" } }, { "course": "MODP", "name": "Алексей", "phone": "998887766", "corp": false, "wishes": { "country": "Россия", "city": "Москва", "online": false, "group ": false, "info": "Позвоните мне для уточнения деталей" } } ] }
Сгенерируем схему данных для этого сообщения в формате JSON, используя онлайн-редактор https://extendsclass.com/json-schema-validator.html. Результат будет следующим:
{ "definitions": {}, "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://example.com/object1672485649.json", "title": "Root", "type": "object", "required": [ "apps" ], "properties": { "apps": { "$id": "#root/apps", "title": "Apps", "type": "array", "default": [], "items":{ "$id": "#root/apps/items", "title": "Items", "type": "object", "required": [ "course", "name", "email", "phone", "corp", "wishes" ], "properties": { "course": { "$id": "#root/apps/items/course", "title": "Course", "type": "string", "default": "", "examples": [ "TTIS" ], "pattern": "^.*$" }, "name": { "$id": "#root/apps/items/name", "title": "Name", "type": "string", "default": "", "examples": [ "Анна" ], "pattern": "^.*$" }, "email": { "$id": "#root/apps/items/email", "title": "Email", "type": "string", "default": "", "examples": [ "anna@email.ru" ], "pattern": "^.*$" }, "phone": { "$id": "#root/apps/items/phone", "title": "Phone", "type": "string", "default": "", "examples": [ "123456789" ], "pattern": "^.*$" }, "corp": { "$id": "#root/apps/items/corp", "title": "Corp", "type": "boolean", "examples": [ true ], "default": true }, "wishes": { "$id": "#root/apps/items/wishes", "title": "Wishes", "type": "object", "required": [ "city", "online", "group ", "number_of_students" ], "properties": { "city": { "$id": "#root/apps/items/wishes/city", "title": "City", "type": "string", "default": "", "examples": [ "Казань" ], "pattern": "^.*$" }, "online": { "$id": "#root/apps/items/wishes/online", "title": "Online", "type": "boolean", "examples": [ true ], "default": true }, "group ": { "$id": "#root/apps/items/wishes/group ", "title": "Group ", "type": "boolean", "examples": [ true ], "default": true }, "number_of_students": { "$id": "#root/apps/items/wishes/number_of_students", "title": "Number_of_students", "type": "integer", "examples": [ 20 ], "default": 0 } } } } } } }
Получили файл формата JSON, который перечисляет поля данных, обозначенные в исходном сообщении, с указанием их типов и обязательности. По умолчанию все найденные поля отмечены как обязательные (required). А строка «$schema»: http://json-schema.org/draft-07/schema# означает, что при генерации этой схемы данных редактор опирался на 7-ю версию черновика стандарта JSON-схемы. В отличие от XML, схема данных для формата JSON до сих пор находится в статусе черновика. Дополнительно этот редактор позволяет включить в описание схемы примеры значений.
Генерация схемы для JSON-сообщенияПредставим эти же данные в формате XML, который используется в протоколе SOAP, также воспользовавшись одним из многочисленных онлайн-конвертеров. Например, https://esstudio.site/json2xml/ позволяет получить XML-документ из JSON в 2-х вариантах представления полей: в виде отдельных элементов или в виде атрибутов одного элемента. Рассмотрим оба из них. Сперва сгенерируем XML из JSON, записав данные в отдельные элементы (поля), и получим следующее тегированное сообщение древовидной структуры:
<root> <apps> <appsItem> <wishes> <info>Позвоните мне для уточнения деталей</info> <group >false</group > <online>false</online> <city>Москва</city> <country>Россия</country> </wishes> <corp>false</corp> <phone>998887766</phone> <name>Алексей</name> <course>MODP</course> </appsItem> <appsItem> <wishes> <company>Банк</company> <group >true</group > <online>false</online> <city>Астана</city> <country>Казахстан</country> </wishes> <corp>true</corp> <email>nikita@email.bank</email> <phone>1122334455</phone> <name>Никита</name> <course>BAMP</course> </appsItem> <appsItem> <wishes> <info>Прошу связаться со мной в телеграм</info> <group >true</group > <online>true</online> <country>Россия</country> </wishes> <corp>false</corp> <phone>987654321</phone> <name>Лиза</name> <course>OAIS</course> </appsItem> <appsItem> <wishes> <group >false</group > <online>true</online> </wishes> <corp>false</corp> <email>boris@email.ru</email> <name>Борис</name> <course>MODP</course> </appsItem> <appsItem> <wishes> <number_of_students>20</number_of_students> <group >true</group > <online>true</online> <city>Казань</city> </wishes> <corp>true</corp> <phone>123456789</phone> <email>anna@email.ru</email> <name>Анна</name> <course>TTIS</course> </appsItem> </apps> </root>
Сгенерируем 2-ой вариант, используя атрибуты:
<root> <apps> <appsItem course="MODP" name="Алексей" phone="998887766" corp="false"> <wishes country="Россия" city="Москва" online="false" group ="false" info="Позвоните мне для уточнения деталей"> </wishes> </appsItem> <appsItem course="BAMP" name="Никита" phone="1122334455" email="nikita@email.bank" corp="true"> <wishes country="Казахстан" city="Астана" online="false" group ="true" company="Банк"> </wishes> </appsItem> <appsItem course="OAIS" name="Лиза" phone="987654321" corp="false"> <wishes country="Россия" online="true" group ="true" info="Прошу связаться со мной в телеграм"> </wishes> </appsItem> <appsItem course="MODP" name="Борис" email="boris@email.ru" corp="false"> <wishes online="true" group ="false"> </wishes> </appsItem> <appsItem course="TTIS" name="Анна" email="anna@email.ru" phone="123456789" corp="true"> <wishes city="Казань" online="true" group ="true" number_of_students="20"> </wishes> </appsItem> </apps> </root>
За счет «склейки» нескольких элементов в один с разными атрибутами, выходное сообщение получилось чуть лаконичнее. Однако, рекомендуется хранить данные в элементах, а не в атрибутах из-за ограничений последний. В частности, атрибуты не могут содержать множественные значения, их сложнее расширять для последующих изменений и они не могут описывать сложные объекты, т.е. структуры. Поэтому для описания данных лучше использовать элементы, а в атрибуты записывать атрибутивную информацию, например, метаданные или специфическое описание объекта, такое идентификатор элемента XML.
Сгенерируем схему XML – файл XSD (XML Schema Definition) с помощью онлайн-генератора https://www.convertsimple.com/convert-xml-to-xsd-xml-schema/.
Для варианта с элементами результат будет следующим:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element name="apps"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="appsItem"> <xs:complexType> <xs:sequence> <xs:element name="wishes"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="info"/> <xs:element type="xs:boolean" name="group"/> <xs:element type="xs:boolean" name="online"/> <xs:element type="xs:string" name="city"/> <xs:element type="xs:string" name="country"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element type="xs:boolean" name="corp"/> <xs:element type="xs:integer" name="phone"/> <xs:element type="xs:string" name="name"/> <xs:element type="xs:string" name="course"/> <xs:element type="xs:string" name="email"> <xs:complexType> <xs:simpleContent> <xs:extension></xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Для XML с атрибутами получим такую схему XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element name="apps"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="appsItem"> <xs:complexType> <xs:sequence> <xs:element name="wishes"> <xs:complexType> <xs:sequence></xs:sequence> <xs:attribute name="country" type="xs:string"/> <xs:attribute name="city" type="xs:string"/> <xs:attribute name="online" type="xs:string"/> <xs:attribute name="group" type="xs:string"/> <xs:attribute name="info" type="xs:string"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="course" type="xs:string"/> <xs:attribute name="name" type="xs:string"/> <xs:attribute name="phone" type="xs:string"/> <xs:attribute name="corp" type="xs:string"/> <xs:attribute name="email" type="xs:string"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Если сравнить JSON и XML-документы, можно сделать очевидный вывод о тяжеловесности XML-формата. Впрочем, текстовый человеко-читаемый JSON, применяемый в GraphQL и REST API, далеко не самый легковесный формат сериализации. Есть еще YAML, который занимает меньше места за счет структурирования данных не с помощью специальных символов {} и [], как в JSON, а через отступы. Сегодня именно этот формат часто используется для представления конфигурации приложений, а также для спецификации Open API (Swagger). Для примера конвертируем рассматриваемое JSON-сообщение в YAML-формат с помощью онлайн-конвертера https://www.json2yaml.com/ и получим следующий документ:
--- apps: - course: TTIS name: Анна email: anna@email.ru phone: '123456789' corp: true wishes: city: Казань online: true 'group ': true number_of_students: 20 - course: MODP name: Борис email: boris@email.ru corp: false wishes: online: true 'group ': false - course: OAIS name: Лиза phone: '987654321' corp: false wishes: country: Россия online: true 'group ': true info: Прошу связаться со мной в телеграм - course: BAMP name: Никита phone: '1122334455' email: nikita@email.bank corp: true wishes: country: Казахстан city: Астана online: false 'group ': true company: Банк - course: MODP name: Алексей phone: '998887766' corp: false wishes: country: Россия city: Москва online: false 'group ': false info: Позвоните мне для уточнения деталей
К сожалению, мне не удалось найти онлайн-генератора для YAML-файла, зато обнаружила интересный инструмент для генерации классов на разных языках программирования из YAML-описания. Например, здесь https://jsonformatter.org/yaml-to-python можно сгенерировать из YAML-документа классы на Python, а здесь https://jsonformatter.org/yaml-to-java – на Java. Также конвертер поддерживает генерацию классов на других языках программирования, полный перечень можно посмотреть здесь: https://jsonformatter.org/yaml-tools-online. Пример практического использования этого инструмента я описываю в новой статье.
В заключение посмотрим, как выглядит это же самое сообщение в бинарном формате Protobuf, который используется в технологии gRPC. Конвертируем исходное JSON-сообщение в формат Protobuf с помощью онлайн-конвертера https://json2pb.vercel.app/ и получим следующий документ:
message AutoGenerate { message Apps { string course = 1; string name = 2; string email = 3; string phone = 4; bool corp = 5; message Wishes { string city = 1; bool online = 2; bool group = 3; uint32 number_of_students = 4; } Wishes wishes = 6; } repeated Apps apps = 1; }
Конвертация JSON-сообщения в формат protobuf
Как видно из примера, Protobuf-сообщение включает схему данных, т.е. название полей и их тип, однако, человеку понять значение того или иного поля невозможно из-за их преобразования. При сериализации данных, т.е. переводе их в бинарный вид из нулей и единиц, сохраняются не имена полей, а их уникальные номера. Это делает процесс передачи данных более эффективным по сравнению с текстовыми форматами, такими как JSON или XML. Впрочем, Protobuf не предназначен для чтения человеком, главное преимущество этого формата – высокая скорость передачи данных по сети.
Резюмируя рассмотренные форматы сериализации данных, следует подчеркнуть, что все они имеют разную скорость преобразования данных в битовую последовательность и обратно, а также размер выходного сообщения. Помимо этих критериев нужно учитывать также удобство использования формата и возможность эволюции схемы. Впрочем, выбор формата данных чаще всего относится к области ответственности ИТ-архитектора или ведущего разработчика, а не аналитика. Однако, аналитику важно понимать основные характеристики наиболее популярных форматов сериализации данных, чтобы представлять в них примеры входящих и исходящих сообщений при интеграции информационных систем, а также схемы данных для их верификации.
Разработка ТЗ на информационную систему по ГОСТ и SRS
Код курса
TTIS
Ближайшая дата курса
24 февраля, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.
Подробнее познакомиться с этими темами, а также другими основами архитектуры и интеграции информационных систем вам помогут курсы Школы прикладного бизнес-анализа в нашем лицензированном учебном центре обучения и повышения квалификации системных и бизнес-аналитиков в Москве:
- Основы архитектуры и интеграции информационных систем
- Разработка ТЗ на информационную систему по ГОСТ и SRS