JSON Toolkit

Редактори, командний рядок та інструментарій автоматизації

Головне: Редактори розвʼязують «добре бачити, правильно редагувати», а командний рядок — «пакетно, повторювано». На кожному боці є кілька інструментів, що лишаються корисними десятиліття.

Початковий~10 хв читанняОпубліковано 2026-10-30Оновлено 2026-10-30
Обкладинка статті про редактори, командний рядок та інструментарій автоматизації

Коротко: обирайте редактор за сценарієм — CodeMirror 6 для утилітарних сайтів і мобільних, Monaco лише коли потрібен повний досвід IDE; пакетну роботу доручайте jq плюс трьом перевіркам CI для синтаксису, структури й стилю, і завжди передавайте аргументи через jq --arg.

Епоха ручної перевірки JSON мала б закінчитися: усе, що машина може повторити, не залишайте людському оку.

1. Редактори в браузері

1.1 Мінімальна інтеграція CodeMirror 6

import { EditorView, basicSetup } from 'codemirror';
import { json, jsonParseLinter } from '@codemirror/lang-json';
import { linter, lintGutter } from '@codemirror/lint';

const view = new EditorView({
  parent: document.getElementById('editor')!,
  doc: '{"hello": "json"}',
  extensions: [
    basicSetup,
    json(),
    linter(jsonParseLinter()),
    lintGutter(),
    EditorView.updateListener.of((update) => {
      if (update.docChanged) {
        // Зробіть debounce перед важкою роботою; не форматуйте на кожне натискання
        scheduleParse(update.state.doc.toString());
      }
    }),
  ],
});

Чотири моменти:

  1. json() дає підсвічування синтаксису й сполучення дужок — не пишіть своє;
  2. jsonParseLinter() створює маркери помилок на рівні рядка й стовпця; поєднайте з lintGutter(), щоб показувати іконки поруч із номерами рядків;
  3. updateListener обов'язково треба debounce; виклик JSON.parse на ста тисячах рядків при кожному натисканні помітно гальмуватиме;
  4. Великі документи потребують оптимізацій поза EditorView.lineWrapping, щоб не відображати все одразу (CodeMirror 6 за замовчуванням відображає за вікном перегляду, що є покращенням порівняно зі старими версіями).

1.2 Згортання й структура

CodeMirror 6 має вбудоване згортання; у сценаріях JSON ви зазвичай згортаєте за «об'єктом/масивом»:

import { foldGutter, foldKeymap } from '@codemirror/language';
import { keymap } from '@codemirror/view';

З foldGutter() і keymap.of(foldKeymap) користувачі можуть згортати довгі масиви комбінацією клавіш.

1.3 Вибір між CodeMirror і Monaco

Вимір CodeMirror 6 Monaco
Розмір пакета Малий, модульний Великий (кілька мегабайт)
Мобільні Добре підтримуються Посередній досвід
Мовні сервіси Треба будувати свої Багаті, вбудовані
Ціна кастомізації Низька Середня

Утилітарні сайти й мобільність на першому місці → CodeMirror; повний досвід IDE (кілька файлів, перехід до визначення, доповнення) → Monaco.

2. Командний рядок: шість частих рецептів jq

jq для JSON — те саме, що sed + awk для тексту; вивчення лише малої частини його синтаксису покриває вісімдесят відсотків повсякденних потреб.

# 1. Вибір полів (найпоширеніше)
jq '.data.items[].name' response.json

# 2. Фільтр + переформування
jq '.data.items[] | select(.price < 10) | {id, price}' response.json

# 3. Агрегати (довжина, сума, максимум)
jq '[.items[] | .price] | {count: length, total: add, max: max}' response.json

# 4. Групування й агрегація
jq '[.items[]] | group_by(.category) | map({category: .[0].category, count: length})' response.json
# 5. Об'єднати кілька файлів у масив
jq -s '.' part-*.json > merged.json

# 6. Обробка JSON Lines рядок за рядком
jq -c 'select(.level == "error")' app.jsonl

# Поширені перемикачі виводу
jq -r '.data.name'      # Прибрати лапки, щоб чисто передати в оболонку
jq -c '.'               # Компактний вивід, один рядок
jq --arg id "$ID" '.id == $id'   # Передавати аргументи безпечно, уникаючи ін'єкції через склеювання

--arg вартий окремої згадки: склеювання змінної безпосередньо в вираз ламається, щойно значення містить лапки, тоді як --arg дозволяє jq самому обробити екранування.

2.1 Інші інструменти стисло

Інструмент Призначення Одним реченням
yq Конвертація YAML/JSON/XML Синтаксис, схожий на jq, робоча конячка для конфігураційних файлів
dasel Уніфіковані запити між форматами Підтримує JSON/YAML/TOML/XML/CSV
fx Інтерактивний перегляд JSON Клікайте в терміналі, добре для дослідження
jless Посторінковий перегляд у терміналі Як less, із згортанням і пошуком
gron Розгортання JSON у рядки, придатні для grep Чудовий інструмент, щоб з'ясувати «на якому рівні це поле»
ajv-cli Перевірка схем Перевіряти файли JSON у CI

Ідея gron особливо варта знання:

$ echo '{"a":{"b":[1,2]}}' | gron
json = {};
json.a = {};
json.a.b = [];
json.a.b[0] = 1;
json.a.b[1] = 2;

Після розгортання grep може знайти шлях, що набагато швидше за розгортання рівень за рівнем у редакторі.

3. Три шари перевірки в CI

Шар Інструмент Що означає збій
Синтаксис JSON.parse / jq empty Сам файл зламаний
Структура ajv-cli + схема Відсутні поля, неправильні типи
Стиль Prettier Неузгоджене форматування, шумні diff
# Синтаксис: пакетно перевірити кожен json-файл у репозиторії
find . -name '*.json' -not -path './node_modules/*' -print0 \
  | xargs -0 -n1 jq empty

# Структура: перевірити за схемою
npx ajv-cli validate -s schemas/order.json -d 'fixtures/orders/*.json' --strict=false

# Стиль: лише перевірка, без змін
npx prettier --check "**/*.json"

Потрібні всі три шари, бо їхні повідомлення про помилки зовсім різні: jq empty каже лише «який рядок зламаний», ajv каже «яке поле порушує яке ключове слово», а Prettier каже лише «форматування неузгоджене».

4. Хуки pre-commit

# Приклад .husky/pre-commit (фрагмент)
npx lint-staged
{
  "lint-staged": {
    "*.json": ["prettier --write", "jq empty"]
  }
}

Будьте обережні з конфігураційними файлами інструментів, як-от package.json і tsconfig.json; не дозволяйте Prettier недбало змінювати їхні відступи — деякі інструменти чутливі до форматування (валідний JSON не повинен бути, але на практиці це спричиняло проблеми). Можна виключити їх окремо.

5. Поради щодо налагодження

  1. Використовуйте jq -e як перевірку: код виходу дорівнює 1, коли результат виразу — false або null, тож його можна одразу вставити в скрипти як перевірку;
  2. jq 'paths' перелічує всі шляхи, даючи швидкий огляд структури незнайомого документа;
  3. jq '.. | objects | keys' знаходить кожну назву ключа, що коли-небудь зустрічалася, що зручно для пошуку неузгодженого написання;
  4. Форматуйте перед порівнянням у редакторі: неформатований diff — чистий шум; структурне порівняння, як-от /diff, точніше.

6. Чек-лист

  • [ ] Маркери помилок редактора точні до рядка й стовпця, а розбір проходить debounce;
  • [ ] Скрипти команди передають аргументи через jq --arg, а не склеюють рядки;
  • [ ] CI має всі три шари перевірки (синтаксис/структура/стиль);
  • [ ] pre-commit обробляє лише додані файли, щоб повне сканування не сповільнювало коміти;
  • [ ] Версії інструментів закріплені в package.json або .tool-versions.

Часті питання

Як обирати між CodeMirror 6 і Monaco?

Для утилітарних сайтів і мобільних надавайте перевагу CodeMirror 6: він малий, модульний, добре підтримується на мобільних, а підсвічування синтаксису, сполучення дужок і згортання можна компонувати за потреби. Звертайтеся до Monaco лише коли потрібен повний досвід IDE з кількома файлами, переходом до визначення й доповненням — ціною багатомегабайтного пакета й вищих зусиль на кастомізацію.

Чому CI потребує перевірки синтаксису, структури й стилю разом?

Три шари повідомляють зовсім різні помилки: jq empty каже, який рядок зламаний, ajv каже, яке поле порушує яке ключове слово, а Prettier каже лише, що форматування неузгоджене. Відкидання одного шару робить помилки інших легко неправильно прочитати, тож тримайте всі три й зупиняйтеся, щойно якийсь шар зазнає збою.

Чи покладатися на pre-commit замість перевірки в CI?

Ні. Хуки обробляють лише додані файли, що дає зворотний зв'язок за хвилину, але не може покрити весь репозиторій чи зміни, що обходять коміт. CI відповідає за повноту: тримайте pre-commit на доданих файлах, а повне сканування залишайте CI.