Przekształcanie i tworzenie obiektów JSON za pomocą jq
Przekształcaj dane za pomocą map, to_entries i konstruowania obiektów, aby tworzyć nowe ładunki JSON.
Przekształcanie i tworzenie obiektów JSON za pomocą jq to bezpłatna lekcja DevOps Bootcamp na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej DevOps Bootcamp, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs DevOps Bootcamp zawiera 4 lekcji w sumie.
Po co przekształcać JSON?
Surowy JSON z API lub plików dziennika rzadko ma dokładnie taką strukturę, jakiej Państwo potrzebują. Mogą Państwo otrzymać duży obiekt, z którego potrzebne są tylko konkretne pola, albo chcieć zmienić nazwy kluczy, spłaszczyć zagnieżdżone struktury lub zbudować zupełnie nowy payload do wysłania do innej usługi.
jq to lekki i potężny procesor JSON działający w wierszu poleceń, który umożliwia wykonywanie takich przekształceń w jednym potoku. W tej lekcji poznają Państwo trzy podstawowe techniki zmiany struktury danych:
- Tworzenie obiektów — zbudowanie nowego obiektu JSON od podstaw
- map — zastosowanie przekształcenia do każdego elementu tablicy
- to_entries / from_entries — potraktowanie par klucz-wartość obiektu jako tablicy, aby można było je filtrować i ponownie zbudować
Wszystkie przykłady zakładają, że jq jest zainstalowany (apt install jq / brew install jq).
Podstawy tworzenia obiektów
Najbardziej podstawową funkcją jq jest tworzenie obiektów: umieszczanie wyrażeń w {}, aby zbudować nowy obiekt JSON. Mogą Państwo wybrać pola, które mają zostać uwzględnione, oraz nadać im własne nazwy.
Składnia:
{ newKey: .existingField }— zmiana nazwy pola{ name, age }— skrócona składnia, gdy nowy klucz ma taką samą nazwę jak pole{ total: (.price * .qty) }— obliczenie wartości bezpośrednio w wyrażeniu
Poniższy fragment odczytuje JSON produktu i tworzy jego uproszczoną strukturę z obliczanym polem subtotal.
#!/usr/bin/env bash
# Object construction: pick and rename fields
product='{
"id": 42,
"name": "Widget Pro",
"price": 9.99,
"qty": 3,
"warehouse": "EU-West"
}'
echo "$product" | jq '{
productId: .id,
name,
subtotal: (.price * .qty)
}'Tworzenie obiektów z zagnieżdżonych danych
JSON spotykany w praktyce jest często zagnieżdżony. jq pozwala odwoływać się do zagnieżdżonych ścieżek wewnątrz konstruktora obiektu, jednocześnie spłaszczając strukturę.
W wyrażeniu określającym wartość konstruktora używają Państwo notacji ścieżki z kropkami:
{ city: .address.city }{ lat: .location.coords.lat }
Poniższy przykład pobiera głęboko zagnieżdżony rekord użytkownika i tworzy płaskie podsumowanie, odpowiednie jako wiersz nagłówkowy pliku CSV lub treść żądania API.
#!/usr/bin/env bash
user='{
"id": "u-001",
"profile": {
"displayName": "Ada Lovelace",
"contact": { "email": "ada@example.com", "phone": "+44-700" }
},
"plan": "pro"
}'
echo "$user" | jq '{
id,
name: .profile.displayName,
email: .profile.contact.email,
plan
}'Przekształcanie tablic za pomocą map
map(expr) jest odpowiednikiem jq konstrukcji for-each: stosuje expr do każdego elementu wejściowej tablicy i zwraca nową tablicę o tej samej długości.
Najważniejsze informacje:
map(expr)jest skróconym zapisem[.[] | expr]- Wyrażenie wewnątrz może być dowolnym filtrem jq — także tworzeniem obiektu
- Można połączyć je z
select(), aby filtrować dane przed przekształceniem
Poniższy fragment przetwarza listę zamówień, zachowując tylko pola potrzebne w wykazie wysyłkowym.
#!/usr/bin/env bash
orders='[
{"orderId": 1, "customer": "Alice", "total": 42.50, "status": "shipped"},
{"orderId": 2, "customer": "Bob", "total": 18.00, "status": "pending"},
{"orderId": 3, "customer": "Carol", "total": 99.99, "status": "shipped"}
]'
# Produce a shipping manifest: only shipped orders, slim fields
echo "$orders" | jq '[
.[] | select(.status == "shipped") | {
id: .orderId,
recipient: .customer,
amount: .total
}
]'map z polami obliczanymi
Wewnątrz map mogą Państwo obliczać nowe wartości, konwertować typy i łączyć pola — a nie tylko je kopiować. Typowe wzorce obejmują:
- Interpolację ciągów znaków:
"\(.first) \(.last)" - Działania arytmetyczne:
(.price * 1.2 | round)dla narzutu w wysokości 20% - Wyrażenia warunkowe:
if .score >= 90 then "A" else "B" end
Poniższy przykład wzbogaca listę pracowników, dodając obliczane pole fullName oraz etykietę seniority na podstawie liczby lat doświadczenia.
#!/usr/bin/env bash
staff='[
{"first": "Grace", "last": "Hopper", "years": 15},
{"first": "Alan", "last": "Turing", "years": 4},
{"first": "Linus", "last": "Torvalds","years": 9}
]'
echo "$staff" | jq 'map({
fullName: "\(.first) \(.last)",
years,
seniority: (if .years >= 10 then "senior" elif .years >= 5 then "mid" else "junior" end)
})'Zrozumienie to_entries
to_entries przekształca obiekt JSON w tablicę par {key, value}. Umożliwia to wykonywanie operacji na tablicach (map, select, sort) na polach obiektu — czego nie można zrobić bezpośrednio na obiekcie.
Przykładowe przekształcenie:
- Wejście:
{"a": 1, "b": 2} - Wyjście:
[{"key": "a", "value": 1}, {"key": "b", "value": 2}]
Operacją odwrotną jest from_entries, która ponownie przekształca tę tablicę w obiekt. Razem tworzą idiom to_entries | map(...) | from_entries służący do przekształceń na poziomie obiektu.
#!/usr/bin/env bash
# Demonstrate to_entries and from_entries
config='{"host": "db.local", "port": 5432, "ssl": true}'
echo "--- to_entries output ---"
echo "$config" | jq 'to_entries'
echo "--- round-trip back to object ---"
echo "$config" | jq 'to_entries | from_entries'Filtrowanie kluczy za pomocą to_entries
Jednym z najbardziej praktycznych zastosowań to_entries jest dynamiczne filtrowanie kluczy, które mają zostać zachowane lub usunięte, na podstawie samej nazwy klucza — czego nie można zrobić za pomocą tworzenia obiektu, gdy nazwy kluczy nie są wcześniej znane.
Wzorzec:
to_entries | map(select(.key | test("regex"))) | from_entriesto_entries | map(select(.key != "secret")) | from_entries
Poniższy fragment usuwa wszystkie klucze zaczynające się od podkreślenia (pola wewnętrzne/prywatne), zanim przekaże obiekt konfiguracji do zewnętrznej usługi.
#!/usr/bin/env bash
raw_config='{
"endpoint": "https://api.example.com",
"timeout": 30,
"_internalToken": "s3cr3t",
"_debugMode": true,
"retries": 3
}'
# Remove any key starting with underscore
echo "$raw_config" | jq '
to_entries
| map(select(.key | startswith("_") | not))
| from_entries
'Dynamiczna zmiana nazw kluczy za pomocą to_entries
Tworzenie obiektu umożliwia zmianę nazw kluczy, gdy ich nazwy są znane w momencie zapisu. to_entries pozwala zmieniać nazwy kluczy programowo — na przykład konwertować camelCase na snake_case lub dodawać prefiks.
Wewnątrz map aktualizują Państwo pole .key każdego wpisu, a następnie przekazują wynik do from_entries:
map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase)— konwersja camelCase na snake_casemap(.key |= "app_" + .)— dodanie prefiksu do każdego klucza
Przykład dodaje prefiks APP_ do wszystkich nazw zmiennych środowiskowych, aby utworzyć dla nich przestrzeń nazw przed wstrzyknięciem do kontenera.
#!/usr/bin/env bash
env_vars='{"host": "localhost", "port": "8080", "debug": "false"}'
# Add APP_ prefix and uppercase all keys
echo "$env_vars" | jq '
to_entries
| map({ key: ("APP_" + (.key | ascii_upcase)), value })
| from_entries
'with_entries: wygodny skrót
Wzorzec to_entries | map(...) | from_entries jest tak często używany, że jq udostępnia jego skróconą wersję: with_entries(expr).
Jest dokładnie równoważny, ale bardziej zwięzły:
with_entries(.value |= . * 2)— podwojenie każdej wartości liczbowejwith_entries(select(.value != null))— usunięcie kluczy, których wartości wynoszą nullwith_entries(.key |= ascii_upcase)— zamiana wszystkich kluczy na wielkie litery
Poniższy fragment usuwa wszystkie klucze, których wartością jest null lub pusty ciąg znaków — to częsty etap czyszczenia danych przed wysłaniem żądania PATCH do interfejsu REST API.
#!/usr/bin/env bash
patch_body='{
"name": "Mehmet",
"email": "",
"phone": null,
"city": "Istanbul"
}'
# Drop empty/null fields before PATCH
cleaned=$(echo "$patch_body" | jq '
with_entries(select(.value != null and .value != ""))
')
echo "Cleaned payload:"
echo "$cleaned"
# In practice you would pipe to curl:
# curl -s -X PATCH https://api.example.com/users/1 \
# -H "Content-Type: application/json" \
# -d "$cleaned"Łączenie map i tworzenia obiektów w potoku
Rzeczywiste przekształcenia łączą wiele operacji jq. Typowy potok przygotowujący payload API może:
- Przefiltrować wejściową tablicę za pomocą
map(select(...)) - Zmienić strukturę każdego elementu za pomocą tworzenia obiektu
- Dodać pola obliczane
- Posortować wynik
Poniższy przykład odczytuje listę metryk serwerów, zachowuje tylko serwery o wysokim użyciu procesora i tworzy zwięzły payload alertu gotowy do wysłania metodą POST do webhooka.
#!/usr/bin/env bash
metrics='[
{"host": "web-01", "cpu": 23, "mem": 60, "region": "eu"},
{"host": "web-02", "cpu": 91, "mem": 88, "region": "eu"},
{"host": "db-01", "cpu": 78, "mem": 95, "region": "us"},
{"host": "db-02", "cpu": 12, "mem": 40, "region": "us"}
]'
alerts=$(echo "$metrics" | jq '[
.[] | select(.cpu > 75 or .mem > 85) | {
server: .host,
region,
severity: (if .cpu > 90 or .mem > 90 then "critical" else "warning" end),
metrics: { cpu: .cpu, mem: .mem }
}
] | sort_by(.severity)')
echo "$alerts"Budowanie nowego obiektu JSON z wielu źródeł
jq może scalać dane wejściowe i tworzyć obiekty korzystające z wielu źródeł JSON za pomocą operatora dodawania + oraz wiązania zmiennych z użyciem as $var.
Przydatne wzorce:
obj1 + obj2— scalenie dwóch obiektów (w przypadku konfliktu kluczy wygrywa wartość po prawej stronie)--argjson— przekazanie drugiego dokumentu JSON jako zmiennej$ENV— bezpośredni odczyt zmiennych środowiskowych wewnątrz jq
Poniższy fragment scala podstawową konfigurację z nadpisaniami zależnymi od środowiska — to częsty wzorzec zarządzania konfiguracją aplikacji zgodnie z metodologią 12-factor w skryptach powłoki.
#!/usr/bin/env bash
base_config='{
"logLevel": "info",
"timeout": 30,
"retries": 3,
"database": "postgres://db.local/app"
}'
env_overrides='{
"logLevel": "debug",
"database": "postgres://db.staging/app_staging"
}'
# Merge: overrides win on conflicts
merged=$(echo "$base_config" | jq --argjson overrides "$env_overrides" '. + $overrides')
echo "Merged config:"
echo "$merged"Sprawdzenie wiedzy: to_entries a map
Mają Państwo następujący obiekt JSON i należy usunąć wszystkie klucze, których wartość jest mniejsza od 0, tworząc nowy obiekt zawierający wyłącznie wartości nieujemne. Które wyrażenie jq poprawnie realizuje to zadanie?
Wejście: {"a": 10, "b": -3, "c": 0, "d": 5}
Podsumowanie lekcji: przekształcanie JSON za pomocą jq
Omówiono najważniejsze techniki zmiany struktury JSON za pomocą jq:
- Tworzenie obiektów
{}— budowanie nowych obiektów przez wybieranie, zmianę nazw i obliczanie pól na podstawie danych wejściowych map(expr)— stosowanie dowolnego przekształcenia do każdego elementu tablicy, w tym tworzenie zagnieżdżonych obiektów i używanieselect()do filtrowaniato_entries/from_entries— konwersja obiektu na tablicę par{key, value}, co umożliwia operacje na kluczach i wartościach, a następnie konwersja z powrotemwith_entries(expr)— zwięzły skrót pełnego potoku to_entries → map → from_entries- Scalanie obiektów za pomocą
+i--argjsonw payloadach pochodzących z wielu źródeł
Te elementy można łączyć: filtrować za pomocą select, zmieniać strukturę przez tworzenie obiektów, wzbogacać danymi obliczanymi i łączyć wszystko w jednym czytelnym wyrażeniu jq. Opanowanie tych wzorców pozwala przetwarzać praktycznie dowolny payload JSON bezpośrednio w powłoce, bez pisania osobnego skryptu w Pythonie lub Node.
Często zadawane pytania
Czy lekcja „Przekształcanie i tworzenie obiektów JSON za pomocą jq” jest bezpłatna?
Tak — pełny tekst „Przekształcanie i tworzenie obiektów JSON za pomocą jq” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu DevOps Bootcamp, przejdź na CoddyKit PRO. Kurs DevOps Bootcamp zawiera 4 lekcji w sumie.
Co nauczysz się w „Przekształcanie i tworzenie obiektów JSON za pomocą jq”?
Przekształcaj dane za pomocą map, to_entries i konstruowania obiektów, aby tworzyć nowe ładunki JSON. Ćwiczysz DevOps Bootcamp z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć DevOps Bootcamp?
Nie wymagamy żadnego doświadczenia. DevOps Bootcamp w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Przekształcanie i tworzenie obiektów JSON za pomocą jq”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji DevOps Bootcamp?
Tak. Każda lekcja DevOps Bootcamp zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Filtrowanie i wybieranie JSON za pomocą potoków jq
- Przekształcanie i tworzenie obiektów JSON za pomocą jq
- Korzystanie z REST API za pomocą curl i jq
- Edycja plików konfiguracyjnych YAML za pomocą yq