#import "template.typ": *

#import "@preview/codelst:2.0.1": sourcecode, sourcefile

// #import "diagrams/main.typ" as main_algo

// Take a look at the file `template.typ` in the file panel
// to customize this template and discover how it works.
#show: project.with(
  title: "Форматы хранения и передачи данных XML и JSON",
  authors: (
    "<NAME>. ИДз-21-21.",
  ),
)

#show figure: set block(breakable: true)

#outline()

= Форматы хранения и передачи данных XML и JSON. Основные понятия

XML (eXtensible Markup Language) и JSON (JavaScript Object Notation) — два популярных формата для хранения и передачи данных в веб-приложениях и между системами. XML представляет собой язык разметки, который использует теги для описания структуры данных, в то время как JSON — это текстовый формат, использующий пары "ключ-значение" для представления данных. Оба формата широко используются благодаря своей гибкости и возможности легко передавать данные между различными платформами и языками программирования.

= Области применения

XML и JSON применяются в самых разных областях, включая веб-разработку, обмен данными между серверами и клиентами, конфигурацию программного обеспечения и многое другое.

- *XML*:
  - Веб-службы (SOAP)
  - Конфигурационные файлы (например, для Java приложений)
  - Документы и электронные публикации

- *JSON*:
  - Веб-API (RESTful сервисы)
  - Конфигурационные файлы (например, для JavaScript и других языков)
  - Хранение и передача данных в NoSQL базах данных (например, MongoDB)

= Структура и наборы правил. Примеры кода

== XML

XML использует теги для обозначения элементов данных и их вложенности. Вот простой пример XML-документа:

#figure(
  caption: [Простой пример `xml`],
  sourcecode()[```xml
  <note>
    <to>Elena</to>
    <from>Ivan</from>
    <heading>Reminder</heading>
    <body>Please buy me a coffee!</body>
  </note>
  ```]
) <xml-example-simple>

Основные правила XML:

- Все элементы должны иметь закрывающий тег.
- Теги чувствительны к регистру.
- Документ должен иметь один корневой элемент.

== JSON

JSON представляет данные в формате "ключ-значение". Вот пример JSON-документа:

#figure(
  caption: [Простой пример `json`],
  sourcecode()[```json
  {
    "note": {
      "to": "Elena",
      "from": "Ivan",
      "heading": "Reminder",
      "body": "Please buy me a coffee!"
    }
  }
  ```]
) <json-example-simple>

Основные правила JSON:

- Данные представляются в виде пар "ключ-значение".
- Ключи заключаются в двойные кавычки.
- Строки также заключаются в двойные кавычки.
- Объекты разделяются запятыми.

Так же стоит отметить официальный сайт с грамматикой, где подробнее описаны правила с иллюстрациями @json-official

В качестве примера использования и примеров кода я написал небольшой web-сервис на языке программирования Go @golang-official.

#figure(
  caption: "Файл с web-сервисом",
  sourcefile(
    file: "main.go",
    read("main.go"),
  )
)

Для запуска программы необходимо выполнить и установленные компилятор Go, который можно скачать на официальном сайте @golang-official. Версия языка должна быть не ниже 1.22.3
```bash
go run main.go
```
После запуска веб-сервер будет доступен на `localhost:8080`

Для проверки работы сервиса необходимо запустить утилиту командной строки curl @curl-official

Для получения ответа в формате xml
```bash
curl --request GET \
  --url 'http://localhost:8080/hello?type=xml&value=world'
```
Ответ от сервера
```xml
<GreetingResp>
    <greeting to="Hello world"></greeting>
</GreetingResp>
```

Для получения ответа в формате json
```bash
curl --request GET \
  --url 'http://localhost:8080/hello?type=json&value=world'
```
Ответ от сервера
```json
{
    "greeting": {
        "to": "Hello world"
    }
}
```

В качестве хорошего примера более сложного файла json. Есть проект по киновселенной звездных войн @swapi-web, в котором собраны все персонажи, планеты, космические корабли и прочее, проект предоставляет возможность скачивать всю информацию через REST-api в формате `json`.
Можно проверить запустив эту команду в терминале

#figure(
  caption: [Команда запроса 10 персонажей из франшизы "Звёздные войны"],
  sourcecode()[```bash
    curl "https://swapi.dev/api/people?page=1" | yq -oj -p=json > swapi.json
  ```],
) <curl-swapi>

Обычно, при скачивании файлов формата `json`, индентация и переносы строк опускаются, чтобы сохранить память, так как json строковый тип данных и для каждой новой строки необходимы символы `\n`#footnote[Перенос курсора в начало следующей строки] и \u{23b5}#footnote[Пробел].\ Поэтому в команде из @curl-swapi я использую утилиту `yq` @yq-website, которой я передаю в аргументы результаты выполнения утилиты `curl` через конвейер. `yq` полезна тем, что форматирует файлы, а так же позволяет переводить файлы одного формата в другой, как я покажу в дальнейшем.
Результатом выполнения данной команды будет файл - формата `json`, с 10-ю персонажами франшизы.

#figure(
  caption: [Результат выполнения команды из @curl-swapi],
  sourcefile(
    file: "swapi.json",
    read("swapi.json"),
  ),
) <curl-swapi-result>

Так как тема работы сравнение форматов `xml` и `json`, то я при помощи `yq` переформатирую файл из @curl-swapi-result в формат `xml`.

#figure(
  caption: [Команда преобразования `json` в `xml` при помощи `yq`],
  sourcecode()[```bash
    yq swapi.json -o=xml > swapi.xml
  ```]
) <yq-json-2-xml>

#figure(
  caption: [Результат выполнения команды из @yq-json-2-xml],
  sourcefile(
    file: "swapi.xml",
    read("swapi.xml"),
  ),
) <yq-json-2-xml-result>

Здесь сразу можно заметить различия между этим форматами. Более детальный разбор этих форматов описаны ниже.

= Преимущества и недостатки

== XML

*Преимущества*:

- Гибкость: позволяет создавать сложные иерархические структуры данных.
- Стандартизация: поддерживается множеством стандартов и спецификаций (например, XSLT, XPath).
- Валидация: поддержка схем (XSD) для проверки структуры и содержания данных.

*Недостатки*:

- Объемность: данные в XML могут занимать больше места по сравнению с другими форматами.
- Сложность обработки: требует больше ресурсов для парсинга и обработки.

== JSON

*Преимущества*:

- Легкость: более компактный и легкий для чтения и записи формат.
- Быстрота обработки: требует меньше ресурсов для парсинга по сравнению с XML.
- Совместимость с JavaScript: легко интегрируется в веб-приложения.

*Недостатки*:

- Ограниченная поддержка схем: менее строгие правила для валидации структуры данных.
- Отсутствие комментариев: формат не поддерживает включение комментариев в данные.

= Альтернативы

Кроме XML и JSON, существуют и другие форматы для хранения и передачи данных:

/ YAML: (YAML Ain't Markup Language): человекочитаемый формат, часто используемый для конфигурационных файлов.
#figure(
  caption: [Часть стандартного файла-конфигурации для утилиты lazygit @lazygit-repo, использующий формат `yaml` для управления поведением программы.],
  sourcefile(
    file: "lazy-config.yaml",
    read("lazy-config.yaml"),
  ),
)
/ CSV/TSV: (Comma/Tab-Separated Values): простой текстовый формат для табличных данных. В примере ниже я использовал символ `&`, для разделения значений внутри столбца, но данные могут быть испорчены или в них может быть неправильно проставлены запятые, тогда произойдет коллизия разделителей @delim-collision. Данный формат плохо подходит для работы с данными, где необходимо учитывать связи между сущностями.

```csv
Ndex,Name,Type
#0566,Archen,Rock&Flying
#0079,Slowpoke,Water&Psychic
```

/ Protobuf: (Protocol Buffers): двоичный формат, разработанный Google для эффективной сериализации структур данных. @protobuf-website

#figure(
  caption: [Пример protobuf, который описывает телефонную книгу (`example.proto`)],
  sourcefile(
    file: "example.proto",
    read("example.proto"),
  ),
)

Для компиляции `.proto` в `.go` необходим `protoc` - компилятор `.proto`-файлов. Для это его необходимо установить в систему как пакет, выполнив команду из @install-protoc-gen-go. Для генерации намнеобходимо запустить компилятор как показано в @compile-protoc-gen-go

#figure(
  caption: [Команда установки утилилиты `protoc`],
  sourcecode()[```bash
    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
  ```]
) <install-protoc-gen-go>

#figure(
  caption: [Команда запуска утилиты `protoc` для генерации `go`-файлов из `.proto`-файлов],
  sourcecode()[```bash
    protoc --go_out=. example.proto
  ```]
) <compile-protoc-gen-go>

#figure(
  caption: [Результат компиляции @install-protoc-gen-go при помощи команды @compile-protoc-gen-go],
  sourcefile(
    file: "example.pb.go",
    read("example.pb.go"),
  ),
) <compiled-protoc-go>

#figure(
  caption: [Установка пакетов из сети для правильной работы программы],
  sourcecode()[```bash
  go mod tidy
  ```]
) <go-mod-tidy>

Теперь я могу через интерфейс сгенерированный в @compiled-protoc-go, использовать структуры в своей программе. Необходимо так же выполнить установку пакетов см. @go-mod-tidy

#figure(
  caption: [Пример использования интерфейса `profobuf`],
  sourcecode()[```go
  p := Person{
      Id:    1234,
      Name:  "<NAME>",
      Email: "<EMAIL>",
      Phones: []*pb.Person_PhoneNumber{
          {Number: "555-4321", Type: pb.PhoneType_PHONE_TYPE_HOME},
      },
  }
  ```]
)

`protobuf` это удобный и эффективный формат работы с данными, к тому же существует множетсво реализация для разных языков, как компилируемых, так и интерпретируемых.

/ TOML: (Tom's Obvious, Minimal Language): формат для конфигурационных файлов, который отличается простотой синтаксиса и удобством для человека.

#figure(
  caption: [Часть стандартного файла-конфигурации проекта менеджера пакетов pip @pip-pyproject-toml, использующий формат `toml` для конфигурации зависимостей проекта.],
  sourcefile(
    file: "pyproject.toml",
    read("pyproject.toml"),
  ),
)

/ BSON: (Binary JSON): бинарный формат сериализации данных, использующийся в MongoDB @bson-in-mongodb, обеспечивающий быструю обработку и меньший размер данных по сравнению с JSON.


#figure(
  table(
    columns: (auto, auto, auto),
    table.header([], [JSON], [BSON]),
    [Кодировка], [Файлы пишутся в текстовом формате.], [Файлы пишутся в бинарном формате.],
    [Скорость], [Быстро читается, но медленнее создается.], [Медленно читается, но быстрее создается и сканируется.],
    [Память], [Меньше по размеру], [Больше по размеру],
    [Кодирование и декодирование], [Можно отправлять по сети, например по http, без кодирования и декодирования.], [Файлы кодируются перед хранением и декодируются перед отображением.],
    [Парсинг], [Человекочитаемый формат, который не требует преобразования.], [Нужно преобразовать, так как они бинарного формата и не человекочитаемы.],
    [Типы данных], [Имеет определенный набор типов данных: строка, логический, число, массив, объект и null.], [Предлагает дополнительные типы данных, такие как bindata для бинарных данных и decimal128 для числовых данных. @bson-spec],
    [Примeнение], [Используется для отправки данных через сеть], [Используется в базах данных],
  ),
  caption: [Различия BSON и JSON]
)

/ MessagePack: бинарный формат сериализации данных, который эффективнее по размеру и скорости по сравнению с JSON.

Помимо широко известных форматов, существуют менее популярные, но все же полезные альтернативы для хранения и передачи данных:

/ Avro: формат сериализации данных от Apache, используемый в проектах Hadoop. Он поддерживает эволюцию схем данных и эффективное сжатие.
/ CBOR: (Concise Binary Object Representation): бинарный формат, предназначенный для компактного представления данных.
/ Thrift: формат и фреймворк от Apache для разработки и сериализации межплатформенных сервисов.
/ UBJSON: (Universal Binary JSON): формат, направленный на предоставление бинарной версии JSON.
/ FlatBuffers: формат сериализации данных, разработанный Google, ориентированный на высокую производительность и минимальные затраты на десериализацию.
/ Ion: формат данных, разработанный Amazon, который сочетает в себе характеристики JSON и BSON с дополнительными возможностями, такими как поддержка схем и аннотаций.
/ Smile: бинарный формат, основанный на JSON, предназначенный для компактного и быстрого хранения и передачи данных.

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

Эти альтернативы могут быть предпочтительнее в зависимости от конкретных требований проекта и условий использования.

= Заключение

В данной работе мы рассмотрели два ключевых формата для хранения и передачи данных — XML и JSON. Оба формата играют важную роль в современной веб-разработке и обмене данными между различными системами.

*XML* (eXtensible Markup Language) обладает высокой гибкостью и позволяет создавать сложные иерархические структуры данных. Он широко используется в веб-службах (SOAP), конфигурационных файлах и электронных публикациях. Преимущества XML включают стандартизацию и поддержку схем валидации (XSD), однако его недостатки заключаются в объемности и сложности обработки данных.

*JSON* (JavaScript Object Notation), с другой стороны, является более легким и компактным форматом, который быстро обрабатывается и легко интегрируется в веб-приложения. JSON широко используется в веб-API (RESTful сервисы), конфигурационных файлах и NoSQL базах данных. Преимущества JSON включают его простоту и совместимость с JavaScript, но он имеет ограниченную поддержку схем и не поддерживает включение комментариев.

Мы также рассмотрели альтернативы XML и JSON, такие как YAML, CSV, Protobuf, TOML и BSON. Каждая из этих альтернатив имеет свои уникальные особенности и области применения, что позволяет выбирать наиболее подходящий формат в зависимости от конкретных требований проекта.

Таким образом, выбор между XML и JSON, а также их альтернативами, зависит от конкретных условий и требований проекта. XML подходит для задач, требующих сложных структур данных и строгой валидации, тогда как JSON предпочтителен для легких и быстрых операций обмена данными в веб-приложениях. Альтернативные форматы могут быть полезны в специфических сценариях, где важны компактность, производительность или удобство для человека.

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

Полный код проекта Вы можете найти в репозитории https://github.com/yan-aint-nickname/uni в директории `practice-6-sem`

#bibliography("bibliography.yaml")
