Skip to content
Kembali ke Blog
Tutorial

Cheat Sheet jq: 30 Pola JSON Command-Line Dunia Nyata

Kuasai jq dengan 30 pola teruji untuk menyaring, mengubah, dan mengekstrak JSON di command line — dari kubectl dan AWS CLI hingga log.

12 menit baca

Cheat Sheet jq: 30 Pola JSON Command-Line Dunia Nyata

Kamu mem-pipe kubectl get pods -o json ke less, lalu terminal membeku di tembok JSON dua megabita. Yang kamu inginkan hanyalah nama setiap pod dengan fase Running. jq mengerjakannya dengan tiga karakter sintaks filter — asalkan kamu kenal kosakatanya.

Ini bukan referensi sintaks lagi. Ini 30 pola yang benar-benar akan kamu ketik, dikelompokkan berdasarkan tugas yang ingin diselesaikan: mengakses, menyaring, mengubah, mengagregasi, memformat, dan menggabungkan dengan alat nyata seperti kubectl, aws, dan docker.

Kapan pakai jq, formatter browser, atau kode?

jq tidak selalu jawaban yang tepat. Tiga pilihan yang jujur:

SituasiAlat terbaikKenapa
Satu respons API, butuh syntax highlight dan nomor barisJSON Formatter di browserDiff visual, tanpa setup, privat di dalam browser
Pipeline shell, pemrosesan log, skrip CI, server jarak jauhjqComposable, scriptable, tidak butuh GUI
Logika bisnis, unit test, percabangan kompleksKode (JS / Python)Debugger sungguhan, tipe, pustaka

Pilih jq ketika tugasnya hidup di dalam pipeline shell — selain itu biasanya lebih mudah di tempat lain.

Instalasi dan pipeline pertama

jq hadir sebagai binary tunggal di semua platform utama:

# macOS
brew install jq

# Debian / Ubuntu
sudo apt install jq

# Windows (winget)
winget install jqlang.jq

Pipeline pertama menggunakan filter identitas:

curl -s https://api.github.com/users/octocat | jq .

Filter . mengambil input dan mengeluarkannya apa adanya, rapi. Itu saja sudah menggantikan sebagian besar momen “biar kubuka JSON ini di editor”.

Lima flag mencakup 90% penggunaan nyata:

FlagKegunaan
-rOutput mentah — menghilangkan tanda kutip di sekitar hasil string
-cKompak — satu nilai JSON per baris (NDJSON)
-sSlurp — membaca semua input ke satu array
-RInput mentah — membaca baris sebagai string, bukan JSON
-nInput null — tidak membaca stdin, memakai null sebagai input

Model mental inti: filter dan pipe

Sebuah filter menerima satu nilai JSON sebagai input dan menghasilkan nol atau lebih nilai JSON sebagai output. Filter disusun dengan pipe |, yang mengirim setiap output filter kiri sebagai input ke filter kanan. Model mentalnya sama dengan pipe shell, hanya saja yang mengalir adalah nilai JSON, bukan byte.

# . — identitas
echo '{"name":"Alice"}' | jq '.'

# .key — akses field
echo '{"name":"Alice"}' | jq '.name'

# .key.sub — path dalam
echo '{"user":{"email":"a@x.com"}}' | jq '.user.email'

# .[] — iterasi elemen array (menghasilkan banyak output)
echo '[{"id":1},{"id":2}]' | jq '.[] | .id'

# Komposisi pipe: setiap output .items[] masuk ke .name
echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq '.items[] | .name'

Itu seluruh tata bahasanya. 30 pola di bawah adalah kombinasi dari primitif-primitif tersebut.

30 pola yang benar-benar akan kamu pakai

Setiap pola menampilkan JSON input, perintah, dan output. Salin mana saja langsung ke terminalmu.

Akses dan ekstraksi (Pola 1–5)

Pola 1 — Akses aman dengan ?

Mengakses field yang mungkin tidak ada tanpa membuat crash:

echo '{"name":"Alice"}' | jq '.address?.city?'
# Output: null

? menekan error pada kunci yang hilang. Tanpa itu, .address.city akan melempar error tipe jika .address tidak ada.

Pola 2 — Akses path dalam

echo '{"user":{"profile":{"email":"a@x.com"}}}' | jq '.user.profile.email'
# Output: "a@x.com"

Pola 3 — Slicing array

echo '[10,20,30,40,50]' | jq '.[1:3]'
# Output: [20, 30]

echo '[10,20,30,40,50]' | jq '.[-1]'
# Output: 50

Indeks negatif dihitung dari belakang. Slice memakai interval setengah terbuka, seperti Python.

Pola 4 — Turun rekursif untuk menemukan setiap kunci yang cocok

echo '{"a":{"name":"x"},"b":[{"name":"y"},{"id":1}]}' | jq '.. | .name? | select(. != null)'
# Output: "x"
#         "y"

.. menelusuri setiap nilai dalam pohon. Digabung dengan .name? dan select, ia mengekstrak setiap field name di kedalaman berapa pun — sangat berguna untuk mengeksplorasi skema JSON yang belum dikenal.

Pola 5 — Daftar semua kunci objek

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys'
# Output: ["apple", "mango", "zebra"]

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys_unsorted'
# Output: ["zebra", "apple", "mango"]

keys mengurutkan alfabetis; keys_unsorted mempertahankan urutan penyisipan.

Menyaring (Pola 6–10)

Pola 6 — Menyaring array berdasarkan kondisi

echo '[{"age":20},{"age":30},{"age":40}]' | jq 'map(select(.age > 25))'
# Output: [{"age":30},{"age":40}]

map(f) menerapkan f pada tiap elemen; select(cond) hanya menyimpan elemen yang memenuhi kondisi.

Pola 7 — Mencocokkan awalan string

echo '[{"name":"api-gateway"},{"name":"web-ui"},{"name":"api-auth"}]' \
  | jq '.[] | select(.name | startswith("api"))'
# Output: {"name":"api-gateway"}
#         {"name":"api-auth"}

Yang juga berguna: endswith("..."), contains("..."), test("^regex$").

Pola 8 — Kondisi gabungan

echo '[{"type":"A","count":5},{"type":"A","count":15},{"type":"B","count":20}]' \
  | jq '.[] | select(.type == "A" and .count > 10)'
# Output: {"type":"A","count":15}

and, or, not bekerja sesuai dugaan.

Pola 9 — Hapus field sensitif

echo '{"user":"alice","password":"s3cret","token":"abc"}' | jq 'del(.password, .token)'
# Output: {"user":"alice"}

del() menerima banyak path dan tidak gagal jika salah satunya hilang.

Pola 10 — Deduplikasi berdasarkan field

echo '[{"id":1,"v":"a"},{"id":2,"v":"b"},{"id":1,"v":"a2"}]' | jq 'unique_by(.id)'
# Output: [{"id":1,"v":"a"},{"id":2,"v":"b"}]

unique mendeduplikasi nilai utuh; unique_by(f) mendeduplikasi berdasarkan hasil filter.

Mengubah (Pola 11–15)

Pola 11 — Mengganti nama field

echo '[{"first_name":"Alice","age":30}]' | jq 'map({name: .first_name, age})'
# Output: [{"name":"Alice","age":30}]

Bentuk singkat {age} setara dengan {age: .age}.

Pola 12 — Menambah field terhitung dengan interpolasi string

echo '[{"first":"Alice","last":"Chen"}]' \
  | jq 'map(. + {fullName: "\(.first) \(.last)"})'
# Output: [{"first":"Alice","last":"Chen","fullName":"Alice Chen"}]

\(expr) mengevaluasi expr dan menyisipkan nilainya ke string.

Pola 13 — Meratakan array bertingkat

echo '[{"tags":["a","b"]},{"tags":["c"]}]' | jq '[.[] | .tags[]]'
# Output: ["a","b","c"]

echo '[[1,2],[3,[4,5]]]' | jq 'flatten'
# Output: [1,2,3,4,5]

flatten menerima argumen kedalaman opsional: flatten(1) hanya mengupas satu level.

Pola 14 — Objek ke array dan sebaliknya

echo '{"a":1,"b":2}' | jq 'to_entries'
# Output: [{"key":"a","value":1},{"key":"b","value":2}]

echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# Output: {"a":1,"b":2}

Pasangan ini memungkinkan transformasi yang membutuhkan iterasi atas kunci objek — hal yang tidak bisa dilakukan langsung oleh sintaks titik.

Pola 15 — Menggabungkan dua objek secara mendalam

echo '{"a":{"x":1},"b":2}' | jq '. * {a:{y:9}, c:3}'
# Output: {"a":{"x":1,"y":9},"b":2,"c":3}

Operator * melakukan deep merge. Untuk merge dangkal pakai + (sisi kanan menang).

Agregasi (Pola 16–20)

Pola 16 — Panjang array, objek, dan string

echo '[1,2,3,4]' | jq 'length'      # 4
echo '{"a":1,"b":2}' | jq 'length'  # 2
echo '"hello"' | jq 'length'        # 5

Pola 17 — Menjumlahkan field

echo '[{"price":10},{"price":25},{"price":5}]' | jq '[.[].price] | add'
# Output: 40

add menjumlah angka, menggabungkan string, atau memfusikan array — tergantung tipe input.

Pola 18 — Pengelompokan berdasarkan field

echo '[{"cat":"A","n":1},{"cat":"B","n":2},{"cat":"A","n":3}]' | jq 'group_by(.cat)'
# Output: [[{"cat":"A","n":1},{"cat":"A","n":3}],[{"cat":"B","n":2}]]

Setiap grup menjadi array dalam. Gabung dengan map untuk agregasi per grup.

Pola 19 — Pengurutan menurun

echo '[{"date":"2026-01-03"},{"date":"2026-01-01"},{"date":"2026-01-02"}]' \
  | jq 'sort_by(.date) | reverse'
# Output: [{"date":"2026-01-03"},{"date":"2026-01-02"},{"date":"2026-01-01"}]

String tanggal ISO 8601 urut dengan benar sebagai string. Format lain perlu di-parse dulu — panduan Unix timestamp membahas epoch detik, milidetik, dan konversi zona waktu secara rinci.

Pola 20 — Maksimum atau minimum berdasarkan field

echo '[{"name":"a","rating":4.1},{"name":"b","rating":4.8},{"name":"c","rating":3.9}]' \
  | jq 'max_by(.rating)'
# Output: {"name":"b","rating":4.8}

min_by, max_by mengembalikan satu elemen. Untuk top N pakai sort_by(.rating) | reverse | .[:N].

Format output (Pola 21–25)

Pola 21 — Output CSV

echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' \
  | jq -r '.[] | [.name, .age] | @csv'
# Output: "Alice",30
#         "Bob",25

@csv mengutip string dan mengescape kutipan internal. -r menghapus kutipan JSON luar supaya CSV langsung bisa dipipe. Untuk konversi bolak-balik penuh antara CSV dan JSON dalam pipeline, lihat panduan konversi CSV ke JSON.

Pola 22 — Output TSV

echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' \
  | jq -r '.[] | [.id, .name] | @tsv'
# Output: 1	Alice
#         2	Bob

Output yang dipisah tab cocok dengan cut, awk, dan column -t.

Pola 23 — Output string mentah

echo '["alpha","beta"]' | jq -r '.[]'
# Output: alpha
#         beta

Tanpa -r, setiap baris akan berkutip. Output mentah adalah yang kamu kirim ke xargs, while read, atau perintah shell lain.

Pola 24 — NDJSON / JSON Lines

echo '[{"a":1},{"a":2}]' | jq -c '.[]'
# Output: {"a":1}
#         {"a":2}

Setiap baris adalah nilai JSON mandiri — format yang dipakai Kafka, Elasticsearch, dan kebanyakan logger terstruktur. -c juga membuang semua whitespace internal.

Pola 25 — Interpolasi string untuk output terformat

echo '[{"name":"server-1","cpu":0.73},{"name":"server-2","cpu":0.21}]' \
  | jq -r '.[] | "\(.name): \(.cpu * 100)% CPU"'
# Output: server-1: 73% CPU
#         server-2: 21% CPU

Bagus untuk ringkasan dan baris log di mana JSON mentah jadi kebisingan.

DevOps di lapangan (Pola 26–30)

Pola 26 — kubectl: nama setiap pod yang sedang berjalan

kubectl get pods -o json \
  | jq -r '.items[] | select(.status.phase=="Running") | .metadata.name'

Pipeline: iterasi pod, simpan hanya Running, emit nama sebagai string mentah.

Pola 27 — AWS EC2: ID instance dengan IP publik

aws ec2 describe-instances \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, .PublicIpAddress // "none"] | @tsv'

Operator alternatif // memberi nilai cadangan saat field null — menghindari null harfiah di kolom output.

Pola 28 — GitHub API: menggabungkan hasil paginasi

for p in 1 2 3; do
  curl -s "https://api.github.com/orgs/myorg/repos?per_page=100&page=$p"
done | jq -s 'add | map(.name)'

-s menampung semua respons sebagai array of arrays, add menggabungkannya, lalu map(.name) mengekstrak nama. Pola umum untuk API paginasi apa pun.

Pola 29 — Menyaring file log terstruktur

cat app.log | jq -c 'select(.level=="error")'

Asumsinya file log berformat NDJSON (satu objek JSON per baris). Gabung dengan tail -f untuk monitoring langsung:

tail -f app.log | jq -c 'select(.level=="error") | {ts: .timestamp, msg: .message}'

Pola 30 — Docker: semua nama image yang sedang dipakai

docker inspect $(docker ps -q) | jq -r '.[].Config.Image' | sort -u

Praktis untuk cek cepat versi image yang berjalan di sebuah host.

Error umum dan cara memperbaikinya

Setiap pengguna jq menabrak yang ini. Tahu solusinya lebih awal hemat berjam-jam.

Cannot iterate over null (null)

Field input yang kamu iterasi bernilai null atau hilang. Dua perbaikan:

# Opsi A: operator opsional
echo '{}' | jq '.items[]?'
# Output: (tidak ada, tanpa error)

# Opsi B: operator alternatif dengan default
echo '{}' | jq '(.items // [])[]'
# Output: (tidak ada, tanpa error)

Pakai ? kalau ingin melompat diam-diam. Pakai // [] kalau ingin memaksa array kosong konkret supaya filter berikutnya tetap jalan.

Cannot index array with "key"

Kamu menulis .foo padahal nilai saat ini adalah array. Tambahkan [] untuk iterasi:

# Salah
echo '{"users":[{"name":"Alice"}]}' | jq '.users.name'
# Error: Cannot index array with "name"

# Benar
echo '{"users":[{"name":"Alice"}]}' | jq '.users[].name'
# Output: "Alice"

Masalah kutipan shell

Bungkus seluruh program jq dengan kutip tunggal, pakai kutip ganda di dalam untuk literal string:

# Aman di mana saja
jq '.users[] | select(.role == "admin")'

# Rusak — kutip ganda ditafsir shell lebih dulu
jq ".users[] | select(.role == \"admin\")"

Kasus pinggir PowerShell Windows

PowerShell tidak memperlakukan kutip tunggal dengan cara yang sama. Lebih baik pakai kutip ganda di sekitar program dan escape kutipan dalam, atau pakai here-string:

jq "@'
.users[] | select(.role == \"admin\")
'@"

Untuk hal-hal non-sepele, simpan filter dalam file .jq dan jalankan jq -f filter.jq.

Salah pakai -r

-r hanya berpengaruh pada hasil bertipe string. Kalau dipakai pada objek, yang keluar tetap objek JSON biasa:

echo '{"a":1}' | jq -r '.'
# Output: {"a":1}     ← tidak berubah; -r tidak punya yang perlu dihapus

Kalau ingin field tertentu tanpa kutip, pilih dulu field itu: jq -r '.a'.

jq menolak JSON dengan komentar atau koma akhir

echo '{"a": 1, /* catatan */ "b": 2,}' | jq .
# parse error: Invalid numeric literal

jq mengikuti RFC 8259 JSON secara ketat — tanpa komentar, tanpa koma akhir, tanpa kunci tanpa kutip. Jika file-nya JSON5 atau JSONC (umum pada file konfigurasi), bersihkan ekstensi tersebut sebelum mem-pipe ke jq. Panduan format JSON5 dan JSONC menjelaskan parser mana yang mendukungnya dan cara mengubahnya menjadi JSON ketat.

jq vs alternatif: gron, fx, jj, yq

jq bukan satu-satunya, dan kadang alat lain lebih cepat:

AlatKeunggulanKapan dipakai
gronMeratakan JSON jadi path yang bisa di-grepMengeksplorasi skema asing — kamu tidak tahu di mana kuncinya
fxEksplorer TUI interaktif dengan highlightMembaca JSON besar dengan mata
jjJauh lebih cepat dari jq, sintaks terbatasLoop panas yang memproses jutaan rekaman
yqBahasa filter sama tapi untuk YAMLManifest Kubernetes dan konfigurasi CI
JSON Formatter di browserSyntax highlight, pesan error presisi, tanpa instalasiDebug satu respons ketika sedang mengembangkan

Untuk kerja shell harian, jq menang di komposisi. Untuk eksplorasi sekali-sekali, gron sering lebih cepat. Untuk YAML pakai yq — jangan mencoba pipe yq lalu jq.

Trik pro untuk pemakaian harian

Beberapa kebiasaan yang bikin jq terasa alami:

  1. Simpan .jqrc di $HOME. Taruh fungsi pembantu di sana, dan semuanya tersedia di setiap panggilan jq:

    def running: select(.status.phase == "Running");
    def table(f): [f] | @tsv;
  2. Pakai jqplay.org untuk filter kompleks. Tempel JSON di kiri, ulik filter di kanan, pindahkan versi yang jalan ke skripmu.

  3. Bangun cheat sheet pribadi dari history. history | grep 'jq ' | sort -u > ~/jq-patterns.txt menangkap setiap pola yang benar-benar pernah kamu pakai.

  4. Kombinasikan dengan JSON Formatter di browser untuk skema yang asing. Jelajahi struktur secara visual dulu untuk menemukan path yang dibutuhkan, baru tulis perintah jq.

  5. Pantau nilai langsung: watch -n 5 "curl -s api.example.com/health | jq '.uptime'" menyegarkan setiap 5 detik — dashboard ops mini tanpa dependensi.

FAQ

Apa itu jq dan kenapa pengembang memakainya?

jq adalah prosesor JSON untuk command line. Ia mengekstrak, menyaring, dan mengubah JSON di pipeline shell tanpa skrip Python atau Node — jalur terpendek dari respons API, file log, atau output kubectl ke field yang kamu butuhkan.

Apakah jq tersedia di Windows?

Tersedia. Instal via winget install jqlang.jq, Chocolatey choco install jq, atau unduh binary dari jqlang.org. Aturan kutip PowerShell berbeda dari bash — kalau ragu, simpan filter di file .jq dan jalankan jq -f filter.jq.

Apa bedanya jq dengan JSON formatter di browser?

JSON Formatter di browser bersifat interaktif — tempel JSON, lihat highlight dan error, salin hasil. jq non-interaktif — jelaskan transformasi sekali, jalankan di pipeline shell. Pakai browser untuk debug satu respons; pakai jq untuk otomatisasi operasi yang sama pada ratusan input.

Kenapa jq bilang “Cannot iterate over null”?

Kamu mencoba iterasi (.[]) atas nilai null — biasanya karena field tidak ada di input. Perbaiki dengan operator opsional .items[]? atau beri default lewat .items // [] | .[].

Bisakah jq mengubah file di tempat?

Tidak langsung — jq menulis ke stdout. Pakai file sementara atau sponge dari moreutils: jq '.version = "2.0"' config.json | sponge config.json. Selalu cadangkan file asli dulu; filter yang salah ketik akan menimpa file.

Bagaimana memakai jq dengan respons curl?

Pipe curl -s ke jq. Flag -s membungkam progress bar curl supaya hanya body JSON yang sampai ke jq:

curl -s https://api.github.com/users/octocat | jq '.name, .blog'

Apa bedanya | di jq dengan | di shell?

Pipe shell memindahkan byte antar-proses. Pipe jq memindahkan nilai JSON antar-filter dalam satu pemanggilan jq. Perintah dengan banyak pipe internal berjalan di satu proses — lebih murah daripada rantai jq | jq | jq.

Apakah jq bisa menangani JSON Lines (NDJSON)?

Bisa, secara native. jq membaca setiap baris sebagai nilai JSON mandiri saat dipisahkan whitespace. Pakai -c untuk mengeluarkan NDJSON dan -s untuk mengumpulkan NDJSON menjadi satu array.

Bagaimana memformat JSON tanpa memfilter?

Pakai filter identitas: cat data.json | jq . atau jq . < data.json. Ia mem-parse, memvalidasi, dan memformat dengan indent dua spasi — tanpa filter.

Adakah alternatif jq dengan GUI?

Ada. fx menyediakan TUI interaktif. Untuk GUI tanpa instalasi, JSON Formatter berbasis browser mencakup kebutuhan eksplorasi dan validasi. Alat web seperti jqplay.org menyediakan jq sendiri dengan preview langsung.

Kapan pakai jq alih-alih menulis skrip Python?

Pilih jq saat tugasnya sekali jalan, muat di pipeline shell, dan tetap dalam semantik saring/ubah/ekstrak. Pindah ke Python kalau butuh unit test, state kompleks, pustaka pihak ketiga, atau logika bercabang yang melebihi keterbacaan file .jq.

Bagaimana memakai regex di jq?

jq memaparkan regex lewat test("pattern"), match("pattern"), capture("pattern"), dan scan("pattern"), semuanya dalam sintaks PCRE. Berikan flag sebagai argumen kedua: test("abc"; "i") untuk abaikan huruf besar/kecil. match mengembalikan offset dan capture; scan mengeluarkan setiap kecocokan yang tidak tumpang tindih.

Bagaimana menjaga karakter non-ASCII tetap utuh di output jq?

jq mengeluarkan UTF-8 secara default dan mempertahankan karakter non-ASCII selama kamu tidak memakai -a / --ascii-output. Kalau muncul \u00e9 atau \u4e2d\u6587 menggantikan karakter aslinya, biasanya locale terminal penyebabnya: pastikan $LANG adalah id_ID.UTF-8 atau en_US.UTF-8 dan hindari flag -a.

Poin-poin utama

  1. Model mental dulu: satu filter masuk, nol atau lebih nilai JSON keluar, disusun dengan |. Sisanya cuma sintaks.
  2. Belajar per tugas, bukan per operator: 30 pola di atas mencakup sekitar 95% pemakaian jq harian.
  3. Tangani null secara eksplisit: ? untuk melompat diam-diam, // default untuk fallback konkret. Sebagian besar perbaikan Cannot iterate over null lewat salah satu dari keduanya.
  4. Tahu kapan jq adalah alat yang salah: respons tunggal lebih cocok di JSON Formatter browser; YAML milik yq; logika kompleks milik kode nyata.
  5. Pasangkan dengan stack yang ada: jq bersinar di dalam curl, kubectl, aws, docker, dan pipeline log. Pakailah sebagai lem, bukan lapisan logika.

Untuk alur JSON terkait, lihat panduan format JSON5 dan JSONC untuk ekstensi sintaks file konfigurasi, dan panduan konversi CSV ke JSON untuk migrasi format data di mana jq masuk ke dalam pipeline. Kalau JSON-mu punya timestamp, panduan Unix timestamp membahas jebakan saat mengubah field tanggal.

Artikel Terkait

Lihat semua artikel