JSON Toolkit

Memilih Alat Diff JSON: Diff Teks, Diff Struktural, dan Visualisasi

Intinya: Diff teks menemukan di mana file berbeda; diff struktural memutuskan apakah isinya ekuivalen. Memilih lapisan yang tepat mencegah urutan kunci disalahartikan sebagai insiden.

Menengah±9 menit bacaDiterbitkan 2026-10-31Diperbarui 2026-10-31
Sampul artikel memilih alat diff JSON

Intinya: diff teks menemukan perubahan (urutkan kunci dengan jq -S terlebih dahulu), diff struktural memutuskan ekuivalensi (sejajarkan array berdasarkan kunci utama), dan visualisasi hanya menjelaskan atau meninjau perubahan; pisahkan ketiga lapisan itu di CI.

Dua dokumen JSON yang terlihat berbeda tidak berarti isinya berbeda. Pilih lapisan perbandingan yang tepat sebelum memilih alat.

1. Tiga jenis "diff" bukan hal yang sama

Banyak tim menganggap "membandingkan JSON" sebagai satu tindakan, lalu menemui masalah yang sama dalam skenario berbeda. Ada baiknya memisahkan tiga lapisan:

Lapisan Yang dibandingkan Yang diungkapkan Penggunaan tipikal
Diff teks Byte dan baris mentah Indentasi, urutan kunci, spasi, baris baru Penyimpangan konfigurasi, tinjauan kode
Diff struktural Objek dan array yang telah di-parse Kunci yang ditambahkan atau dihapus, nilai yang berubah, perubahan elemen array Regresi API, migrasi data
Diff visual Bagaimana perbedaan disajikan Perubahan berada di level mana, seberapa besar dampaknya Tinjauan manusia, diskusi tim

Diff teks tidak memerlukan dependensi, cepat, dan terintegrasi secara alami dengan Git. Kelemahannya adalah ia tidak tahu apa pun tentang semantik JSON. Dua dokumen yang sepenuhnya ekuivalen akan menyala merah dan hijau jika urutan kunci atau indentasinya berbeda. Diff struktural adalah kebalikannya: ia mem-parse dulu lalu membandingkan, sehingga mengenali bahwa sebuah nilai hanya berpindah. Tetapi ia membutuhkan strategi penyejajaran array yang tepat; jika tidak, satu penyisipan salah dibaca sebagai penulisan ulang total.

Visualisasi bukan algoritma ketiga. Ia merender output dari dua lapisan lainnya agar orang dapat dengan cepat mengonfirmasi apakah perbedaannya sesuai harapan. Ia baik untuk penilaian manusia dan buruk sebagai pengganti pemeriksaan otomatis. Mencampur lapisan-lapisan itu biasanya menghasilkan pipeline CI yang selalu merah dan tim yang belajar mengabaikannya.

2. Diff teks: rapikan urutan kunci dengan jq -S terlebih dahulu

Untuk melihat sekilas dua file, kombinasi termurah adalah jq -S plus diff -u. Flag -S mengurutkan kunci objek secara rekursif, menormalkan dokumen yang isinya identik tetapi urutan kuncinya berbeda:

jq -S . a.json > a.sorted.json
jq -S . b.json > b.sorted.json
diff -u a.sorted.json b.sorted.json

Ini menghilangkan positif palsu yang paling umum. RFC 8259 mendefinisikan objek sebagai kumpulan tak berurutan, sehingga {"a":1,"b":2} dan {"b":2,"a":1} adalah nilai yang sama. Namun diff teks menandai setiap baris sebagai berubah. Mengurutkan terlebih dahulu membuat blok merah jauh lebih dekat ke masalah nyata.

Perhatikan bahwa jq -S hanya mengurutkan kunci; ia tidak mengurutkan array. Urutan array bermakna dalam JSON, dan [1,2] bukan nilai yang sama dengan [2,1], jadi alat itu tidak akan membuat keputusan tersebut untuk Anda. Jika array secara konseptual adalah himpunan tak berurutan, urutkan sendiri berdasarkan kunci utama sebelum membandingkan.

Ada detail lain yang perlu diingat: diff keluar dengan kode 1 ketika menemukan perbedaan, tetapi file yang hilang atau error izin juga menghasilkan exit non-nol. Di CI, jangan perlakukan setiap kode non-nol sebagai "konten berubah", atau path yang salah ketik akan dilaporkan sebagai perubahan data. Pola yang lebih aman memverifikasi file terlebih dahulu, lalu menangani perbedaannya:

if ! diff -u a.sorted.json b.sorted.json; then
  echo "JSON content differs" >&2
  exit 1
fi

delta membuat diff teks mudah dibaca

Output diff -u mentah memang berfungsi, tetapi baris panjang dan JSON yang bersarang dalam melelahkan untuk dibaca. delta adalah filter diff yang menambahkan penyorotan sintaks, nomor baris, dan warna latar yang lebih jelas:

diff -u a.sorted.json b.sorted.json | delta

Ia awalnya dibuat sebagai pager Git, sehingga juga dapat mengambil alih git diff. Bagi orang yang membaca sepuluh diff konfigurasi sehari, alat semacam ini meningkatkan kecepatan membaca, bukan akurasi algoritmik. Pilihan umum lainnya adalah git diff --no-index --word-diff, yang membandingkan pada granularitas kata dan bekerja baik untuk JSON terkompresi yang disimpan dalam baris sangat panjang.

Satu peringatan: memperindah tampilan tidak menghilangkan perbedaan palsu. Jika urutan kunci belum dinormalkan, delta hanya membuat kebisingan itu lebih cantik. Urutan yang benar selalu normalkan dulu, hiasi kemudian.

3. Diff struktural: jsondiffpatch memahami semantik

Ketika pertanyaannya adalah apakah dua potongan data ekuivalen secara semantik, gunakan diff struktural. Opsi paling umum di ekosistem JavaScript adalah jsondiffpatch, yang mengembalikan objek delta yang mendeskripsikan perubahan alih-alih baris teks dengan penanda + dan -:

import { create } from 'jsondiffpatch';

const instance = create();
const delta = instance.diff(
  { id: 1, tags: ['a', 'b'], enabled: true },
  { id: 1, tags: ['a', 'c'], enabled: false },
);

console.log(JSON.stringify(delta, null, 2));

Delta membedakan kunci yang ditambahkan, kunci yang dihapus, nilai yang diganti, dan elemen array yang dipindahkan. Artinya Anda dapat menelusuri delta langsung dalam asersi: undefined jika tidak ada perbedaan, atau deskripsi per jalur jika ada. Berbeda dari diff teks, ia tidak terganggu oleh indentasi, urutan kunci, atau penulisan angka seperti 1e3 versus 1000.

Yang tak kalah penting, output diff struktural dapat memberi masukan ke alur kerja patching. jsondiffpatch menyediakan patch dan reverse, sehingga delta dapat diterapkan ke objek asli dan dibatalkan kemudian. Satu catatan: delta yang dihasilkan otomatis tidak sama formatnya dengan JSON Patch yang ditulis tangan, dan mengonversi di antara keduanya membutuhkan usaha. Untuk pendekatan perbandingan yang lebih luas, lihat JSON diff dan perbandingan.

4. Cara menghilangkan perbedaan palsu akibat urutan kunci

Urutan kunci bukan sekadar menjengkelkan; ia dapat menghasilkan kesimpulan yang salah. Ikuti tiga langkah saat menyelidiki:

  1. Sebelum membandingkan, normalkan urutan kunci secara rekursif dengan jq -S atau alat setara.
  2. Hapus field yang berubah setiap kali dijalankan, seperti timestamp, requestId, dan traceId.
  3. Pastikan tidak ada kunci duplikat. Kunci duplikat diselesaikan dengan "yang terakhir menang" saat parsing, sehingga diff teks melihatnya sementara diff struktural tidak.
jq -S 'del(.meta.timestamp, .meta.requestId)' a.json > /tmp/a.json
jq -S 'del(.meta.timestamp, .meta.requestId)' b.json > /tmp/b.json
diff -u /tmp/a.json /tmp/b.json

Alur ini sangat cocok untuk penyimpangan konfigurasi. Jalankan staging dan produksi melalui normalisasi yang sama, dan apa pun yang tersisa adalah perbedaan yang memang perlu dijelaskan. Simpan aturan filter dalam skrip berversi alih-alih mengetiknya ulang dari ingatan. Untuk sisi pengeditan dan pembuatan skrip toolchain, lihat Editor, command line, dan otomasi.

5. Array: sejajarkan berdasarkan indeks atau id?

Array adalah bagian paling rawan kesalahan dalam perbandingan JSON. Dengan penyejajaran indeks bawaan, menyisipkan satu record di awal menggeser setiap elemen setelahnya, dan alat menandai semuanya sebagai berubah. Alatnya tidak rusak; strategi penyejajarannya yang salah.

Penyejajaran Berfungsi saat Kelebihan Risiko
Berdasarkan indeks Urutan array membawa makna bisnis Sederhana, tidak perlu field tambahan Satu penyisipan menyebabkan positif palsu berantai
Berdasarkan kunci utama Elemen adalah himpunan dengan id unik Mendeteksi penyisipan, penghapusan, dan perpindahan Membutuhkan kunci yang stabil dan unik
Subsekuens umum terpanjang Urutan penting tetapi penyisipan diperbolehkan Lebih tahan banting daripada pengindeksan murni Lebih sulit dijelaskan, biaya lebih tinggi

jsondiffpatch menggunakan objectHash untuk menyatakan kunci utama, mengindeks elemen array sebelum membandingkan:

const instance = create({
  objectHash: (item: { id?: string; sku?: string }) => item.id ?? item.sku,
});

Dengan jq biasa, Anda dapat mengurutkan terlebih dahulu lalu menggunakan diff teks:

jq -S 'sort_by(.id)' items.json > items.sorted.json

Kompromi dengan penyejajaran id adalah perubahan posisi tidak lagi dihitung sebagai perbedaan. Jika bisnis perlu mengetahui bahwa sebuah record berpindah dari posisi 2 ke posisi 5, bandingkan juga field urutan eksplisit; jangan mengandalkan isi himpunan saja.

6. Diff visual: lapisan yang dibuat untuk manusia

Output diff struktural dirancang untuk mesin, bukan untuk rapat. Ketika Anda perlu menjelaskan perubahan kepada orang lain, visualisasi lebih efektif:

  • Editor diff VS Code bagus untuk tinjauan file per file, dengan panel berdampingan dan sorotan inline.
  • Penampil pohon seperti JSON Crack dan JSON Hero menunjukkan perubahan berada di level mana.
  • jsondiffpatch menyertakan formatter HTML yang merender delta sebagai tampilan kaya yang dapat dilipat.

Nilai visualisasi adalah konteks. Diff teks mengatakan baris 88 berubah; tampilan pohon mengatakan baris 88 milik data.items[3].price. Namun visualisasi biasanya memuat seluruh dokumen ke peramban atau aplikasi desktop. Sebelum membuka payload produksi, pastikan apakah alat itu menghitung secara lokal atau mengunggah ke server.

7. Tiga praktik untuk menempatkan diff di CI

Pertama, normalkan sebelum membandingkan. Tetapkan indentasi, urutkan kunci secara rekursif, dan filter field volatil sebelum diff dijalankan. Jika tidak, CI akan gagal berulang kali karena kebisingan.

Kedua, pilih penyejajaran berdasarkan semantik. Jika array adalah himpunan, sejajarkan berdasarkan kunci utama. Jika ia adalah sekuens, pertahankan penyejajaran indeks. Jangan terapkan satu aturan ke semua API.

Ketiga, asersi nilai, bukan teks. Membandingkan objek yang telah di-parse dalam pengujian jauh lebih stabil daripada membandingkan output JSON.stringify. Ketika pemeriksaan gagal, cetak jalur perbedaan dan nilai sebelum/sesudah alih-alih membuang seluruh payload ke log.

# Print only the differing paths and values, not the entire document
jq -S 'del(.timestamp)' actual.json > /tmp/actual.json
jq -S 'del(.timestamp)' expected.json > /tmp/expected.json
diff -u /tmp/expected.json /tmp/actual.json | head -n 80

Jika sebuah perbedaan perlu dilacak dalam jangka panjang, commit skrip normalisasi dan file ekspektasi bersama-sama. Jika itu penyelidikan sekali pakai, hapus skrip sementara setelahnya agar ia tidak diam-diam menjadi implementasi kedua logika bisnis.

8. Tabel pemilihan alat

Skenario Pilihan pertama Alternatif Pengingat penting
Perbandingan file sesekali Diff VS Code diff -u Format dulu untuk menghilangkan kebisingan
Penyimpangan konfigurasi jq -S + diff delta Filter field volatil
Regresi respons API jsondiffpatch deepdiff Sejajarkan array berdasarkan kunci utama
Menjelaskan perubahan ke tim JSON Crack / JSON Hero Formatter HTML Periksa apakah data diunggah
File sangat besar Ekstraksi subtree jq Penjelajahan jless Jangan memuat seluruh pohon ke memori
Pemeriksaan pra-commit git diff --no-index pre-commit Tangani exit code secara eksplisit

Tidak ada satu alat diff JSON terbaik; yang ada hanyalah alat yang tepat untuk lapisan saat ini. Diff teks menemukan perubahan, diff struktural menilai ekuivalensi, dan visualisasi menjelaskan perubahan. Memisahkan ketiga lapisan jauh lebih andal daripada mencari satu alat yang melakukan semuanya. Untuk penanganan konflik antar-cabang, lanjutkan ke JSON dan merge Git.

FAQ

Apakah jq -S juga mengubah urutan array?

Tidak. -S hanya mengurutkan kunci objek dan membiarkan array dalam urutan aslinya. Array berurutan dalam JSON, sehingga alat itu tidak akan mengubah [1,2] menjadi [2,1]. Jika array secara konseptual adalah himpunan tak berurutan, urutkan secara eksplisit dengan sort_by.

Apakah 1 dan 1.0 nilai yang sama dalam diff struktural?

Sebagian besar parser mengubah keduanya menjadi angka yang sama, sehingga diff struktural biasanya menganggapnya setara, sementara diff teks menandainya berbeda. Gunakan diff struktural untuk memutuskan ekuivalensi dan diff teks untuk memutuskan apakah file identik byte-per-byte.

Bisakah output diff langsung digunakan sebagai JSON Patch?

Tidak secara langsung. Alat diff melaporkan apa yang berbeda, sedangkan JSON Patch mendeskripsikan daftar operasi terurut; format dan semantiknya berbeda. Patch yang dihasilkan otomatis juga cenderung merujuk indeks array, yang menjadi basi di bawah konkurensi. Tambahkan operasi test sebelum menerapkannya.

Bagaimana cara membandingkan file JSON berukuran puluhan megabyte?

Ekstrak dulu subtree yang Anda pedulikan, misalnya dengan jq '.data.items', lalu urutkan berdasarkan kunci utama dan bandingkan. Jangan memuat seluruh pohon ke memori untuk diff rekursif. File yang sangat besar lebih baik ditangani dengan perbandingan streaming atau terpotong, dan biaya memori perlu dinilai secara terpisah.

Bisakah alat diff online membocorkan data saya?

Tergantung implementasinya. Alat front-end murni menghitung di peramban dan tidak mengunggah data; alat yang dirender server mengirim konten ke backend, tempat data mungkin masuk ke log. Sebelum membandingkan konfigurasi produksi atau payload pelanggan, pastikan halaman menghitung secara lokal, dan uji sekali dengan jaringan terputus jika perlu.

Bagaimana memutuskan antara diff teks dan diff struktural?

Untuk melihat sekilas di mana dua file berbeda, urutkan kunci dengan jq -S dan jalankan diff -u. Untuk memutuskan apakah dua dokumen ekuivalen secara semantik, gunakan diff struktural seperti jsondiffpatch dan sejajarkan array berdasarkan kunci utama. Diff teks tidak memerlukan dependensi dan terintegrasi dengan Git, sementara diff struktural tidak terganggu oleh indentasi, urutan kunci, atau penulisan angka.

Mengapa CI tidak boleh menganggap setiap exit code diff non-nol sebagai perbedaan?

diff keluar dengan 1 ketika menemukan perbedaan, tetapi file yang hilang atau error izin juga mengembalikan non-nol. Memperlakukan setiap kode non-nol sebagai "konten berubah" melaporkan path yang salah ketik sebagai perubahan data. Pola yang lebih aman memverifikasi file terlebih dahulu lalu menangani perbedaan secara terpisah.

Haruskah saya melakukan diff file puluhan megabyte di peramban?

Tidak. Ekstrak dulu subtree yang Anda pedulikan dengan jq, lalu urutkan berdasarkan kunci utama dan bandingkan. Memuat seluruh pohon ke memori untuk diff rekursif memakan memori dan waktu jauh lebih banyak. File yang sangat besar lebih baik ditangani dengan perbandingan streaming atau terpotong.