Formatowanie JSON w Bashu: jq i python3
Użyj darmowego Formater i Upiększacz JSON bezpośrednio w przeglądarce — bez instalacji.
Wypróbuj Formater i Upiększacz JSON online →Gdy skrypt deploy zaczyna przetwarzać odpowiedzi API lub walidować pliki konfiguracyjne w CI, umiejętność formatowania JSON w bashu staje się niezbędna. Dwa narzędzia pokrywające 99% rzeczywistych przypadków to jq i python3 -m json.tool — oba niezawodnie formatują JSON w potokach bash, walidują z kodami wyjścia i czysto integrują się z procesami CI/CD. Do jednorazowego podglądu bez terminala przeglądarkowy Formater JSON obsługuje to natychmiast. Ten przewodnik obejmuje instalację jq, formatowanie z potoków i plików, funkcje walidacji, integrację CI/CD w GitHub Actions, hooki pre-commit, wzorce heredoc oraz przypadki, gdy warto sięgnąć po zapasowy moduł ze standardowej biblioteki Pythona.
- •
jq .formatuje I waliduje jednocześnie — kończy działanie z kodem 1 przy nieprawidłowym JSON - • Używaj
jq -ew potokach CI: niezerowe wyjście przy pustym/false/null wyniku - •
jq . file.json > /dev/null && echo "valid"— walidacja bez zmiany wyjścia - •
python3 -m json.tooldziała na każdym systemie bez dodatkowej instalacji - • Nigdy nie rób
jq . f.json > f.json— powłoka obcina plik źródłowy przed odczytaniem przez jq
Czym jest formatowanie JSON w Bashu?
Formatowanie JSON w bashu oznacza przekształcenie zwartego, zminifikowanego JSON w czytelne wyjście z wcięciami. Dane pozostają niezmienione — różnią się tylko białe znaki i podziały wierszy. W kontekście skryptów ma to znaczenie z dwóch powodów: czytelność podczas debugowania i walidacja, gdy formatter sprawdza składnię przy okazji. Narzędzia takie jak jq w pełni parsują JSON przed jego przeformatowaniem, co oznacza, że udane formatowanie jest jednocześnie niejawną weryfikacją poprawności. To podwójne zachowanie — formatowanie i walidacja w jednym kroku — sprawia, że jq jest tak użyteczny w zautomatyzowanych potokach.
{"service":"payments-api","version":"2.4.1","database":{"host":"db-prod-01.internal","port":5432,"pool_size":20},"cache":{"enabled":true,"ttl":300}}{
"service": "payments-api",
"version": "2.4.1",
"database": {
"host": "db-prod-01.internal",
"port": 5432,
"pool_size": 20
},
"cache": {
"enabled": true,
"ttl": 300
}
}jq — formatowanie JSON w Bashu
jq to de facto standard przetwarzania JSON w skryptach powłoki (jq 1.6+, bash 4+). Jest to dedykowany procesor JSON wiersza poleceń, który potrafi formatować, filtrować, przekształcać i walidować JSON. Filtr tożsamości . przepuszcza wejście bez zmian, ale sformatowane. Gdy jq nie może sparsować wejścia, kończy działanie z kodem 1 — to sprawia, że idealnie nadaje się do skryptowania: formatowanie i walidacja to jedna operacja.
Instalacja jq
# macOS brew install jq # Debian / Ubuntu apt-get install -y jq # Fedora / RHEL / CentOS dnf install jq # Alpine (obrazy Docker) apk add --no-cache jq # Weryfikacja jq --version # jq-1.7.1
Formatowanie ze stdin i z pliku
# Przekazanie wbudowanego JSON przez jq
echo '{"host":"db-prod-01.internal","port":5432}' | jq .
# Formatowanie pliku bezpośrednio (wypisuje na stdout)
jq . config/feature-flags.json
# Formatowanie z wcięciem 4 spacji
jq --indent 4 . config/feature-flags.json
# Formatowanie z użyciem tabulacji zamiast spacji
jq --tab . config/feature-flags.jsonZapis sformatowanego wyjścia do pliku
# Zapis sformatowanego wyjścia (NIE przekierowuj z powrotem do tego samego pliku) jq . compact.json > formatted.json # Kompaktowe (minifikacja) — odwrotność formatowania jq -c . formatted.json
jq kończy działanie z kodem 1 przy nieprawidłowym JSON, z kodem 0 przy sukcesie i z kodem 5 przy błędzie użycia. Używaj tego w instrukcjach if i strażnikach || exit 1 w całym skrypcie.Sortowanie kluczy i wyłączanie kolorów
# Sortowanie wszystkich kluczy alfabetycznie (przydatne dla deterministycznych diffów) jq --sort-keys . config/app-config.json # Wyłączenie kolorowego wyjścia przy zapisie do pliku logów jq --monochrome-output . response.json >> deploy.log
Dokumentacja opcji jq
Najczęściej używane flagi jq do formatowania i walidacji:
Walidacja JSON w skrypcie Bash
Walidacja i formatowanie to ta sama operacja w jq — parsuje przed wydrukowaniem. Przekieruj stdout do /dev/null, gdy potrzebujesz tylko kodu wyjścia bez sformatowanego wyjścia. Poniższy wzorzec jest wielokrotnego użytku w skryptach deploy, hookach pre-commit i potokach CI. Gdy po raz pierwszy widzę nieznany payload API podczas analizy incydentu, pierwszą rzeczą, którą robię, jest przepuszczenie go przez jq — ściana zminifikowanego JSON zamienia się w coś, co można faktycznie czytać i debugować.
Wielokrotnego użytku funkcja walidacji
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ Valid JSON: $file"
return 0
else
echo "✗ Invalid JSON: $file" >&2
return 1
fi
}Przerwanie deploymentu przy nieprawidłowym configu
CONFIG="infra/k8s/app-config.json"
validate_json "$CONFIG" || { echo "Aborting deploy: invalid config" >&2; exit 1; }Walidacja wszystkich plików JSON w katalogu
find ./config -name "*.json" | while read -r f; do jq . "$f" > /dev/null 2>&1 || echo "INVALID: $f" done
-e / --exit-status idzie dalej: kończy działanie z kodem 1 również gdy wyjście to false lub null. Użyj jej do sprawdzenia prawdziwości konkretnego pola: jq -e '.feature_flags.new_checkout' config.json.Formatowanie JSON z plików i odpowiedzi API
Dwa główne źródła JSON w skryptach powłoki to pliki na dysku i odpowiedzi HTTP API przez curl. Każde z nich wymaga nieco innego podejścia. Dla plików głównym problemem jest bezpieczna edycja w miejscu. Dla odpowiedzi API kluczowym szczegółem jest wyciszenie paska postępu curl, aby nie uszkadzał wejścia jq.
Bezpieczne formatowanie pliku w miejscu
# Formatowanie i bezpieczne nadpisanie przez plik tymczasowy tmp=$(mktemp) jq --indent 2 . config/feature-flags.json > "$tmp" && mv "$tmp" config/feature-flags.json echo "Formatted config/feature-flags.json"
Formatowanie odpowiedzi curl API
# Formatowanie statusu deploymentu z API DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
Formatowanie i filtrowanie jednocześnie
# Formatowanie + filtrowanie do błędów z endpointu monitoringu
curl -s "https://monitoring.internal/api/events?level=error&limit=10" \
| jq '[.events[] | {id, message, timestamp, service}]' \
|| { echo "Failed to fetch or parse events" >&2; exit 1; }Wzorzec || { ... } jest tu kluczowy. Bez niego nieudany curl lub zniekształcona odpowiedź API cicho przechodzą dalej, a następny krok skryptu operuje na pustych lub częściowych danych. Jeśli potrzebujesz zbadać złożone zagnieżdżone odpowiedzi bez pisania wyrażeń filtrów, przeglądarkowy Formater JSON pozwala wkleić surową odpowiedź i interaktywnie nawigować po drzewie.
Formatowanie JSON w potokach CI/CD
W CI weryfikacja JSON ma największe znaczenie — nieprawidłowy config, który trafia na produkcję, jest znacznie boleśniejszy do wycofania niż awaria potoku. Większość narzędzi dokumentuje jq do jednorazowego użytku w terminalu; poniższe wzorce to te, których używam w produkcyjnych procesach SRE, aby wychwytywać błędy konfiguracji zanim dotrą do slotu deploymentu.
GitHub Actions — walidacja wszystkich konfigów JSON
- name: Validate JSON configs
run: |
echo "Validating JSON configuration files..."
find . -name "*.json" -not -path "*/node_modules/*" | while read -r f; do
if ! jq . "$f" > /dev/null 2>&1; then
echo "::error file=$f::Invalid JSON syntax"
exit 1
fi
done
echo "All JSON files are valid"Hook pre-commit — walidacja staged plików JSON
#!/usr/bin/env bash
set -euo pipefail
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.json$' || true)
[ -z "$STAGED" ] && exit 0
for f in $STAGED; do
jq . "$f" > /dev/null 2>&1 || { echo "Invalid JSON: $f"; exit 1; }
done
echo "JSON validation passed"scripts/validate-json.sh, nadaj mu uprawnienia wykonywania przez chmod +x scripts/validate-json.sh, a następnie utwórz dowiązanie symboliczne: ln -s ../../scripts/validate-json.sh .git/hooks/pre-commit.Formatowanie zmiennych JSON i Heredoc w Bashu
Skrypty powłoki często budują payloady JSON dynamicznie — ze zmiennych środowiskowych, metadanych git lub obliczonych wartości. Najbezpieczniejszy wzorzec to jq -n --arg / --argjson zamiast interpolacji ciągów, która psuje się w momencie, gdy wartość zawiera cudzysłów lub nowy wiersz. Zawsze bierz zmienne w podwójne cudzysłowy przy przekazywaniu do jq, aby zapobiec podziałowi wyrazów na białych znakach w JSON.
Formatowanie przechowywanej odpowiedzi API ze zmiennej
# Zawsze cytuj "$API_RESPONSE" — białe znaki w JSON psują podstawianie bez cudzysłowów echo "$API_RESPONSE" | jq --indent 2 .
Budowanie i formatowanie payloadu z jq -n
payload=$(jq -n \
--arg env "production" \
--arg version "$(git describe --tags)" \
--argjson replicas 3 \
'{environment: $env, version: $version, replicas: $replicas}')
# Podgląd zbudowanego payloadu
echo "$payload" | jq .
# Wysłanie do API
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DEPLOY_API_TOKEN" \
-d "$payload" \
"https://api.deployments.internal/v1/deploys"--arg zawsze wiąże wartość ciągu. --argjson najpierw parsuje wartość jako JSON, więc można przekazywać liczby, wartości logiczne, tablice i obiekty bez cytowania ich wewnątrz wyrażenia filtra.Formatowanie JSON w Bashu bez instalowania jq
Gdy jq jest niedostępny — minimalne obrazy Docker, zablokowane środowiska CI lub systemy, gdzie nie można instalować pakietów — wbudowany moduł json.tool Pythona zapewnia te same podstawowe możliwości. Jest częścią standardowej biblioteki Pythona; jeśli zainstalowany jest Python 3, działa bez żadnych dodatkowych zależności.
# Formatowanie z pliku python3 -m json.tool config.json # Kontrola szerokości wcięcia python3 -m json.tool --indent 2 config.json # Sortowanie kluczy alfabetycznie python3 -m json.tool --sort-keys config.json # Formatowanie ze stdin (np. z curl) curl -s https://api.deployments.internal/v1/status | python3 -m json.tool
python3 -m json.tool jest bardziej rygorystyczny niż jq: odrzuca trailing commas, komentarze i rozszerzenia JSON5. Ta rygorystyczność jest pożądana przy walidacji konfigów produkcyjnych, ale może być problemem przy pracy z nierygorystycznym JSON od narzędzi zewnętrznych. Nie produkuje też kolorowego wyjścia, przez co przeglądanie w terminalu jest mniej wygodne niż z jq przy użytku interaktywnym.# Walidacja z kodem wyjścia (ta sama semantyka co jq)
python3 -m json.tool config.json > /dev/null && echo "valid" || echo "invalid"
# Walidacja ciągu inline
echo '{"service":"payments-api","healthy":true}' | python3 -m json.tool > /dev/null
echo "Exit code: $?" # 0 = validWyjście terminala z podświetlaniem składni
jq domyślnie koloruje wyjście — klucze na niebiesko, ciągi na zielono, liczby na biało. Gdy potrzebujesz pełnego podświetlania składni JSON w przewijalnym pagerze lub debugując duże zagnieżdżone odpowiedzi w sesji terminalowej, bat zapewnia najwygodniejsze doświadczenie. Oba są przydatne do debugowania i interaktywnej inspekcji; żadnego nie należy używać przy zapisie wyjścia do plików lub odpowiedzi API.
Instalacja bat
# macOS brew install bat # Debian / Ubuntu (binarny może nazywać się batcat — utwórz alias jeśli tak) apt-get install -y bat # alias bat=batcat # dodaj do ~/.bashrc jeśli potrzeba # Weryfikacja bat --version # bat 0.24.0
Przeglądanie plików JSON z podświetlaniem składni
# JSON z podświetlaniem w pagerze (naciśnij q aby wyjść) bat config/app-config.json # Bez pagera — wypisz bezpośrednio do terminala bat --paging=never config/app-config.json # Przekazanie wyjścia jq przez bat do kolorowej inspekcji jq '.database' infra/app-config.json | bat --language=json --paging=never
Kolorowe wyjście jq w przewijalnym pagerze
# -C wymusza kolor nawet gdy stdout nie jest tty (np. przy przekazywaniu do less) jq -C . logs/deploy-response.json | less -R
bat / jq -C) tylko do inspekcji terminalowej i debugowania. Usuń kody kolorów ANSI przed zapisem do plików logów lub przekazywaniem do innych narzędzi — użyj jq -M . (--monochrome-output) lub bat --plain.Praca z dużymi plikami JSON w Bashu
Gdy plik JSON przekracza 50–100 MB, ładowanie go do pamięci w domyślnym trybie jq może być powolne lub wywołać OOM na hostach z ograniczoną pamięcią (np. kontenery Docker z limitem 512 MB). jq --stream emituje pary ścieżka/wartość inkrementalnie podczas czytania, bez buforowania całego dokumentu. Dla NDJSON (jeden obiekt JSON na wiersz) jq ma bardziej efektywne natywne podejście.
Strumieniowanie dużego pliku JSON przez jq --stream
# --stream emituje pary [path, scalar] podczas czytania wejścia # Wyodrębnianie wszystkich pól "status" z dużego archiwum logów bez pełnego ładowania jq -c --stream 'if length == 2 and (.[0][-1] == "status") then .[1] else empty end' logs/archive-2026-03.json
NDJSON / JSON Lines — przetwarzanie jednego obiektu na wiersz
# NDJSON: jeden obiekt JSON na wiersz — powszechne w eksportach Kafka, Fluentd i Logstash
# -R czyta surowe wiersze; fromjson? pomija wiersze niebędące prawidłowym JSON
jq -c -R 'fromjson? | {id: .request_id, status: .http_status, latency: .duration_ms}' logs/access-2026-03-13.ndjson > logs/summary.ndjson# Alternatywa pętlą powłoki — przydatna gdy potrzebna obsługa błędów per wiersz
while IFS= read -r line; do
echo "$line" | jq -c '{id: .request_id, status: .http_status}' 2>/dev/null || echo "SKIP: malformed line" >&2
done < logs/access-2026-03-13.ndjsonjq . file.json na --stream, gdy plik jest większy niż 50–100 MB lub gdy proces działa wewnątrz kontenera z limitem pamięci. Dla potoków NDJSON preferuj jq -R 'fromjson?' nad pętlą while read w powłoce — jest znacznie szybsze, ponieważ nie tworzy podpowłoki dla każdego wiersza.Częste błędy
Problem: Powłoka otwiera i obcina plik wyjściowy przed odczytaniem wejścia przez jq. Jeśli źródło i cel to ta sama ścieżka, jq czyta pusty plik.
Rozwiązanie: Najpierw zapisz do tymczasowego pliku przez mktemp, a następnie atomowo zastąp oryginał przez mv.
jq --indent 2 . settings.json > settings.json
tmp=$(mktemp) && jq --indent 2 . settings.json > "$tmp" && mv "$tmp" settings.json
Problem: Bez obsługi błędów skrypt cicho kontynuuje z pustym lub brakującym sformatowanym plikiem gdy JSON jest nieprawidłowy — kolejne kroki kończą się wtedy mylącymi błędami.
Rozwiązanie: Dodaj || { echo '...' >&2; exit 1; } po każdym wywołaniu jq produkującym wyjście używane przez późniejszy krok.
jq . response.json > formatted.json
jq . response.json > formatted.json || { echo "Invalid JSON in response.json" >&2; exit 1; }Problem: curl domyślnie wypisuje pasek postępu na stderr. Gdy stderr jest połączony ze stdout (np. w podpowłokach lub przy przechwytywaniu logów), tekst paska postępu pojawia się w wejściu jq i powoduje błąd parsowania.
Rozwiązanie: Zawsze przekazuj -s (silent) do curl przy przekazywaniu do jq. Użyj -v lub --fail-with-body osobno jeśli potrzebujesz wyjścia diagnostycznego.
curl https://api.payments.internal/config | jq .
curl -s https://api.payments.internal/config | jq .
Problem: Flaga -r / --raw-output usuwa cudzysłowy JSON z wartości ciągów najwyższego poziomu — nie formatuje obiektów ani tablic. Przekazanie -r . do obiektu wejściowego produkuje ten sam zwięzły obiekt, nie wcięte wyjście.
Rozwiązanie: Używaj jq . (bez flagi -r) do formatowania. Zachowaj -r do wyodrębniania wartości ciągów, np. jq -r '.version' config.json.
jq -r . config.json
jq . config.json
jq vs python3 vs json_pp — Szybkie porównanie
Wybór między narzędziami zależy od tego, co jest dostępne w środowisku i czego potrzebujesz poza podstawowym formatowaniem:
Do większości zadań skryptowania bash i CI/CD jq jest właściwym domyślnym wyborem — waliduje, formatuje, filtruje i zapewnia niezawodne kody wyjścia w jednym binarnym pliku bez zależności od środowiska uruchomieniowego. Wróć do python3 -m json.tool gdy nie możesz instalować dodatkowych pakietów, a Python jest już dostępny.
Często zadawane pytania
Jak sformatować plik JSON w miejscu w bashu?
Nigdy nie przekierowuj wyjścia jq z powrotem do tego samego pliku — powłoka obcina plik przed odczytaniem go przez jq. Zamiast tego najpierw zapisz do pliku tymczasowego, a następnie atomowo zastąp oryginał poleceniem mv.
tmp=$(mktemp) jq --indent 2 . config/app-config.json > "$tmp" && mv "$tmp" config/app-config.json echo "Sformatowano pomyślnie"
Jak walidować JSON w skrypcie bash i zakończyć działanie przy błędzie?
Przekaż plik do jq i przekieruj stdout do /dev/null. Użyj ||, aby przechwycić niezerowy kod wyjścia i przerwać skrypt. jq kończy działanie z kodem 1 przy każdym błędzie parsowania, co czyni go niezawodnym narzędziem do weryfikacji w CI.
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ Valid JSON: $file"
return 0
else
echo "✗ Invalid JSON: $file" >&2
return 1
fi
}
validate_json infra/k8s/app-config.json || exit 1Jak formatować JSON w bashu bez instalowania jq?
Użyj wbudowanego modułu json.tool z Pythona 3 — jest częścią standardowej biblioteki i zapewnia poprawnie wcięte wyjście z tą samą semantyką kodów wyjścia co jq.
# Formatowanie z pliku python3 -m json.tool config.json # Formatowanie ze stdin (np. odpowiedź curl) curl -s https://api.internal/status | python3 -m json.tool --indent 2
Jak sformatować odpowiedź curl w bashu?
Zawsze przekazuj -s (silent) do curl, aby paski postępu nie uszkadzały wejścia jq. Przekieruj stdout curl bezpośrednio do jq.
DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
Jak sformatować tylko część pliku JSON używając jq?
Użyj wyrażenia ścieżki jq zamiast filtra tożsamości (.), aby wyodrębnić i sformatować zagnieżdżony obiekt lub tablicę. Wynik sam w sobie jest poprawnym JSON.
# Formatowanie tylko bloku konfiguracji bazy danych
jq --indent 2 '.database' infra/app-config.json
# Formatowanie + filtrowanie tablicy zdarzeń tylko do poziomu error
jq '[.events[] | select(.level == "error") | {id, message, service}]' events.jsonJaki kod wyjścia zwraca jq przy nieprawidłowym JSON?
jq kończy działanie z kodem 1 przy każdym błędzie parsowania, a także gdy flaga -e / --exit-status jest ustawiona i wyjście to false lub null. Kod 0 oznacza, że JSON został poprawnie sparsowany i wyjście jest wartością prawdziwą. Kod 5 oznacza błąd użycia.
# Bezpośrednie sprawdzenie kodu wyjścia
echo '{"ok":true}' | jq . > /dev/null 2>&1; echo "exit: $?" # exit: 0
echo '{bad json}' | jq . > /dev/null 2>&1; echo "exit: $?" # exit: 1
# Flaga -e: wyjście 1 jeśli wynik to false/null
echo 'null' | jq -e . > /dev/null 2>&1; echo "exit: $?" # exit: 1Powiązane narzędzia
Przeglądarkowe alternatywy i uzupełnienia formatowania JSON w bashu — przydatne gdy potrzebujesz interfejsu graficznego, linku do udostępnienia lub pracujesz poza terminalem:
Nadia is a site reliability engineer who lives in the terminal. She writes Bash scripts that process logs, transform data, and orchestrate infrastructure across fleets of servers. She is a heavy user of jq, awk, and sed and writes about shell one-liners, text processing pipelines, data serialisation from the command line, and the practical Bash patterns that SREs reach for when speed matters more than elegance.
Erik is a DevOps engineer who has spent years writing and maintaining the shell scripts that hold CI/CD pipelines together. He writes about Bash best practices, portable POSIX shell, encoding and decoding in shell scripts, secret management from the command line, and the patterns that separate reliable automation scripts from brittle ones. He is a strong believer in making shell scripts readable and testable with tools like bats-core.