Tidak suka iklan? Pergi Bebas Iklan Hari ini

jq One-Liners Filtrasi dan Transformasi JSON dari CLI Tanpa Menulis Skrip

Diperbarui pada

Tujuh resep praktis jq untuk pengembang backend dan DevOps — mencakup select, map, to_entries, del, group_by, dan transformasi API nyata. Input dan output ditampilkan untuk setiap pola.

jq One-Liners: Filter dan Transformasi JSON dari CLI Tanpa Menulis Skrip 1
IKLAN · HAPUS?

Anda sedang melihat respons API yang telah dikompresi di terminal Anda. Anda perlu mengekstrak tiga field, menghilangkan nilai nol, dan mengalirkan hasilnya ke sesuatu yang lain. Menulis skrip Python untuk hal ini membutuhkan 20 baris dan 2 menit yang tidak Anda miliki. jq mengatasinya dalam satu perintah — jika Anda tahu pola-polinnya.

Tujuh resep di bawah ini. Setiap resep mencakup pola yang sering Anda temui saat bekerja dengan respons API atau file log. Input, perintah, dan output ditampilkan untuk setiap resep.

Instalasi

brew install jq        # macOS
apt-get install jq     # Ubuntu/Debian
apk add jq             # Alpine (Docker images)

Resep 1: Ekstrak Field dari Setiap Objek dalam Array

Hal yang paling umum yang akan Anda lakukan dengan jq: mengambil satu field dari setiap item dalam array JSON.

Input (users.json)

[
  {"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"},
  {"id": 2, "name": "Bob",   "email": "bob@example.com",   "role": "user"},
  {"id": 3, "name": "Carol", "email": "carol@example.com", "role": "user"}
]
jq '.[].name' users.json
# → "Alice"
#   "Bob"
#   "Carol"  (newline-separated stream)

.[] mengiterasi setiap elemen dalam array; .name mengambil field tersebut. Outputnya adalah aliran — berguna untuk dialirkan ke perintah lain. Jika Anda membutuhkan array JSON yang benar:

jq 'map(.name)' users.json
# → ["Alice", "Bob", "Carol"]

map(.name) adalah singkatan dari [.[] | .name] — mengaplikasikan ekspresi pada setiap item dan mengelompokkan hasilnya dalam array. Anda akan menggunakan map() sangat sering.

Resep 2: Filter dengan select

Hanya simpan objek yang memenuhi kondisi; buang yang lain.

jq 'map(select(.role == "admin"))' users.json
[
  {"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"}
]

select(expr) mengalirkan item hanya ketika ekspresi bernilai benar — semua yang lain menghilang. Mengelompokkannya dalam map() mengawetkan output sebagai array. Contoh lain:

# Numeric comparison
jq 'map(select(.score > 80))' results.json

# Not-null check
jq 'map(select(.error != null))' events.json

# String contains (requires test)
jq 'map(select(.message | test("timeout")))' logs.json

Resep 3: Mengubah Objek dengan map

Pilih hanya field yang Anda butuhkan dan secara opsional beri nama ulang dalam satu langkah.

jq 'map({name: .name, role: .role})' users.json
[
  {"name": "Alice", "role": "admin"},
  {"name": "Bob",   "role": "user"},
  {"name": "Carol", "role": "user"}
]

Anda sedang membuat literal objek baru untuk setiap item. Untuk mengubah nama key, ubah sisi kiri tanda titik koma:

jq 'map({username: .name, access_level: .role})' users.json

Satu singkatan yang menghemat ketik: {name} setara dengan {name: .name}. Jika Anda ingin field tetap seperti aslinya, Anda tidak perlu menulis kunci dua kali:

jq 'map({id, name, role})' users.json

Resep 4: Ubah Nama Key dengan to_entries dan from_entries

map sangat baik ketika Anda tahu kunci-kunci yang ada. Ketika Anda perlu mengubah kunci-kunci itu sendiri — menambahkan awalan, mengubah konvensi nama, atau mengubah nama berdasarkan lookup — to_entries adalah pola yang tepat.

Input (config.json)

{"api_url": "https://api.example.com", "timeout": 30, "retry_count": 3}
# Add cfg_ prefix to every key
jq 'to_entries | map(.key = "cfg_" + .key) | from_entries' config.json
{"cfg_api_url": "https://api.example.com", "cfg_timeout": 30, "cfg_retry_count": 3}

to_entries mengubah {"k": "v"} ke dalam [{"key": "k", "value": "v"}]. Setelah Anda memodifikasi entri-entri dalam array hasilnya, from_entries mengembangkan kembali objek tersebut. Untuk mengubah satu kunci tertentu tanpa mengganggu yang lain:

jq 'to_entries | map(if .key == "api_url" then .key = "endpoint" else . end) | from_entries' config.json

Resep 5: Hapus Field dengan del

Inversi dari pengubahan: simpan semua dan hapus beberapa field tertentu. Kasus utamanya adalah menghapus data sensitif sebelum mencatat atau sebelum mengirimkan payload ke layanan pihak ketiga.

jq 'map(del(.email))' users.json
[
  {"id": 1, "name": "Alice", "role": "admin"},
  {"id": 2, "name": "Bob",   "role": "user"},
  {"id": 3, "name": "Carol", "role": "user"}
]

Hapus beberapa field secara bersamaan, atau hapus jalur yang terdalam:

# Multiple top-level fields at once
jq 'del(.password, .token, .refresh_token)' user.json

# Nested path
jq 'del(.user.internal_id)' response.json

# All fields named "debug" at any depth (recursive descent)
jq 'del(.. | .debug? // empty)' response.json

Resep 6: Filter, Ubah, dan Urutkan dalam Satu Langkah

Manfaat utamanya adalah menggabungkan primitif-primitif ini. Berikut adalah pola yang sering muncul saat bekerja dengan respons API yang dibagi-bagi: turun ke array yang terdalam, filter, ubah objek-objeknya, dan urutkan hasilnya.

Input (repos.json)

{
  "total_count": 3,
  "items": [
    {"id": 1, "name": "repo-alpha", "stargazers_count": 142, "language": "Go",     "private": false},
    {"id": 2, "name": "repo-beta",  "stargazers_count": 89,  "language": "Python", "private": true},
    {"id": 3, "name": "repo-gamma", "stargazers_count": 310, "language": "Go",     "private": false}
  ]
}
jq '.items
  | map(select(.private == false and .language == "Go"))
  | sort_by(-.stargazers_count)
  | map({name, stars: .stargazers_count})' repos.json
[
  {"name": "repo-gamma", "stars": 310},
  {"name": "repo-alpha", "stars": 142}
]

Alur pipeline:

  • .items — turun ke array yang terdalam
  • map(select(...)) — filter dalam satu langkah; and menggabungkan kondisi
  • sort_by(-.stargazers_count) — menolak nilai untuk pengurutan menurun; sort_by(.field) satu sendiri memberikan pengurutan naik
  • map({name, stars: .stargazers_count}) — penyesuaian akhir; {name} adalah singkatan dari {name: .name}

Resep 7: Hitung Tingkat Log dengan group_by

Analisis frekuensi pada output log terstruktur — tidak perlu database, tidak perlu teknik awk.

Input (logs.json)

[
  {"level": "error", "msg": "connection timeout",     "service": "auth"},
  {"level": "info",  "msg": "request received",       "service": "api"},
  {"level": "error", "msg": "null pointer exception", "service": "worker"},
  {"level": "warn",  "msg": "slow query detected",    "service": "db"},
  {"level": "error", "msg": "rate limit exceeded",    "service": "api"}
]
jq 'group_by(.level) | map({level: .[0].level, count: length}) | sort_by(-.count)' logs.json
[
  {"level": "error", "count": 3},
  {"level": "info",  "count": 1},
  {"level": "warn",  "count": 1}
]

group_by(.level) mengembalikan array dari array — setiap sub-array mengandung semua entri yang memiliki nilai tingkat yang sama. .[0].level mengambil nama tingkat dari item pertama dalam kelompok; length menghitung jumlah entri dalam kelompok tersebut.

Tambahkan pemecahan per-layanan dalam query yang sama:

jq 'group_by(.level) | map({
  level:    .[0].level,
  count:    length,
  services: map(.service) | unique
})' logs.json

Rincian Singkat

Pola-pola di atas dalam bentuk tabel untuk saat Anda membutuhkan pengingat cepat:

Apa yang Anda inginkanEkspresi jq
Semua nilai dari fieldmap(.field)
Filter item yang sesuaimap(select(.field == "val"))
Ubah setiap objekmap({newKey: .oldKey})
Ubah semua kuncito_entries | map(.key = ...) | from_entries
Hapus fieldmap(del(.field1, .field2))
Urutkan naiksort_by(.field)
Urutkan turunsort_by(-.field)
Hitung berdasarkan kelompokgroup_by(.field) | map({key: .[0].field, count: length})
Dapatkan semua kunci dari objekkeys
Hitung jumlah item dalam arraylength
Nilai unik dari fieldmap(.field) | unique

Sebelum Anda Mulai: Kendalikan Blok

Respons API sering kali kembali dalam bentuk kompresi atau sangat terdalam. Jika Anda tidak yakin tentang jalur yang dibutuhkan, tempelkan JSON ke dalam Pemformat JSON — ini membuat tampilan rapi dengan node yang dapat dikompresi sehingga Anda dapat melihat jalur sebelum menulis ekspresi jq . Setelah menjalankan transformasi, alat ini berguna untuk memverifikasi perbedaan sebelum dan sesudah ketika Anda sedang mengubah atau menghapus field dan ingin memastikan tidak ada perubahan yang tidak diinginkan. Bandingkan JSON Tujuh pola ini mencakup sebagian besar pekerjaan mengolah JSON yang Anda lakukan di baris perintah. Keunggulan nyata adalah menggabungkannya — setelah Anda dapat melakukan filter, ubah, dan urutkan, Anda dapat memproses kebanyakan respons API tanpa menyentuh file skrip.

jq One-Liners: Filter dan Transformasi JSON dari CLI Tanpa Menulis Skrip 2

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?