Поле $schema и версионирование

Поле $schema в спецификациях Vega и Vega-Lite определяет ссылку на JSON Schema, используемую для валидации и интерпретации декларативного описания визуализации. Это ключевой элемент системы, обеспечивающий согласованность между версией библиотеки и структурой JSON-спецификации.

В экосистеме Vega каждое описание графика представляет собой JSON-документ, который интерпретируется движком рендеринга. Без явного указания схемы невозможно гарантировать корректное сопоставление полей, типов данных и доступных конструкций языка спецификации.


Роль JSON Schema в архитектуре Vega

JSON Schema в Vega и Vega-Lite выполняет несколько критически важных функций:

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

Система устроена таким образом, что каждая версия Vega и Vega-Lite сопровождается собственной JSON Schema. Это означает, что изменение версии библиотеки часто сопровождается изменением структуры допустимых выражений.


Структура поля $schema

Поле $schema представляет собой строку, содержащую URI, указывающий на конкретную версию JSON Schema.

Пример для Vega-Lite:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      { "a": "A", "b": 28 },
      { "a": "B", "b": 55 }
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": { "field": "a", "type": "nominal" },
    "y": { "field": "b", "type": "quantitative" }
  }
}

Пример для Vega:

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 400,
  "height": 200,
  "data": [
    {
      "name": "table",
      "values": [
        { "x": 1, "y": 28 },
        { "x": 2, "y": 55 }
      ]
    }
  ],
  "marks": [
    {
      "type": "line",
      "from": { "data": "table" },
      "encode": {
        "enter": {
          "x": { "scale": "xscale", "field": "x" },
          "y": { "scale": "yscale", "field": "y" }
        }
      }
    }
  ]
}

Версионирование схемы

Версионирование Vega и Vega-Lite основано на принципах семантического управления версиями (Semantic Versioning), однако с важной практической особенностью: версия схемы напрямую влияет на допустимый синтаксис спецификации.

Формат URI схемы обычно выглядит следующим образом:

  • Vega-Lite: https://vega.github.io/schema/vega-lite/vX.json
  • Vega: https://vega.github.io/schema/vega/vX.json

где X — мажорная версия.

Значение мажорной версии

Мажорная версия фиксирует набор возможностей языка спецификации:

  • добавление новых типов mark;
  • изменение структуры encoding;
  • введение новых трансформаций данных;
  • удаление устаревших конструкций.

Изменение мажорной версии всегда потенциально ломающее.

Минорные и патч-изменения

Хотя URI обычно фиксируется на уровне vX.json, внутри одной мажорной версии возможны:

  • исправления описаний схемы;
  • уточнение типов;
  • расширение допустимых значений без изменения синтаксиса.

Такие изменения не требуют обновления $schema в спецификации.


Зачем фиксировать версию $schema

Явное указание версии схемы решает несколько инженерных задач:

Предсказуемость выполнения

Без фиксированной версии одна и та же спецификация может интерпретироваться по-разному при обновлении библиотеки. Указание $schema устраняет этот риск.

Контроль миграций

При переходе между версиями Vega/Vega-Lite можно определить набор спецификаций, требующих обновления.

Интеграция с инструментами разработки

Редакторы и IDE используют $schema для:

  • подсветки синтаксиса;
  • автодополнения;
  • проверки типов на лету;
  • выявления устаревших полей.

Совместимость и проблемы версионирования

Основная сложность работы с $schema заключается в том, что спецификации часто живут дольше, чем версии библиотек.

Проблема устаревших схем

Ситуация, при которой:

  • спецификация использует $schema v2;
  • runtime обновлён до v5;

может привести к:

  • некорректному рендерингу;
  • игнорированию части полей;
  • ошибкам в трансформациях.

Обратная несовместимость

Некоторые изменения в Vega-Lite затрагивают фундаментальные элементы:

  • изменение логики facet и repeat;
  • переработка системы scale;
  • изменение поведения агрегатов.

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


Различия подхода Vega и Vega-Lite

Хотя оба инструмента используют $schema, их роль различается.

Vega-Lite

Vega-Lite — это высокоуровневая декларативная обёртка. Здесь $schema определяет:

  • упрощённый язык описания графиков;
  • фиксированный набор визуальных примитивов;
  • стандартизированные трансформации.

Основная цель — абстракция сложности Vega.

Vega

Vega — низкоуровневая система визуализации. $schema здесь определяет:

  • полный графический pipeline;
  • точное управление масштабами, сигналами и событиями;
  • детальную модель рендеринга.

Разница в подходе приводит к различиям в стабильности схем: Vega чаще сохраняет обратную совместимость на уровне поведения, тогда как Vega-Lite может менять высокоуровневые абстракции.


Использование CDN и локальных схем

URI в $schema часто указывает на CDN-ресурс:

https://vega.github.io/schema/vega-lite/v5.json

Такой подход позволяет:

  • централизованно обновлять схемы;
  • использовать их в редакторах без локальной установки;
  • синхронизировать документацию и валидаторы.

В некоторых системах применяется локальное хранение схем:

{
  "$schema": "/schemas/vega-lite-v5.json"
}

Это характерно для закрытых сред, где внешние зависимости ограничены.


Валидация и инструменты разработки

JSON Schema используется не только для проверки структуры, но и для построения инструментов разработки.

Основные сценарии:

  • проверка корректности encoding перед рендерингом;
  • анализ данных трансформаций;
  • генерация UI-конструкторов графиков;
  • статический анализ визуализаций в CI/CD.

Инструменты типа редакторов визуализаций опираются на $schema для построения контекстно-зависимых подсказок. Без него спецификация превращается в обычный JSON без семантической информации.


Миграция между версиями схем

Переход между версиями Vega/Vega-Lite требует учета нескольких факторов:

  • изменения в структуре encoding;
  • устаревание mark-типов;
  • переработка системы трансформаций;
  • изменение поведения scale и axis.

Типичный процесс миграции включает:

  • фиксацию текущего $schema;
  • запуск валидатора старой версии;
  • применение автоматических миграций (если доступны);
  • ручную адаптацию сложных частей спецификации.

Практика версионирования в больших проектах

В промышленных системах визуализации используется стратегия жесткой фиксации $schema:

  • каждая визуализация хранит версию схемы;
  • обновление Vega/Vega-Lite происходит пакетно;
  • миграции выполняются централизованно;
  • регрессионные тесты сравнивают рендеринг.

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


Поведение при отсутствии $schema

Если $schema не указан:

  • валидаторы не могут определить версию;
  • IDE теряют контекст автодополнения;
  • интерпретация становится зависимой от runtime версии;
  • повышается риск несовместимости.

В некоторых реализациях используется эвристическое определение версии, но оно не гарантирует корректность.


Эволюция схем в Vega-экосистеме

С течением времени структура $schema стала более стабильной, но её роль усилилась. Если ранние версии использовали схемы преимущественно для проверки структуры, то современные версии включают:

  • строгую типизацию выражений;
  • описание трансформационных пайплайнов;
  • расширенные правила валидации сигналов (Vega);
  • декларативные ограничения для компилятора (Vega-Lite).

Таким образом, $schema превратился из вспомогательного элемента в центральную точку согласования между спецификацией, инструментами разработки и движком визуализации.