İki JSON Dosyasını Karşılaştırma ve Nelerin Değiştiğini Bulma
İki JSON dosyasını karşılaştırmanın en hızlı yolu, her ikisini de yan yana bir diff aracına yapıştırmak, aynı şekilde biçimlendirmek ve vurgulanan satırları okumaktır. Zor kısım genellikle karşılaştırma değildir. Gürültüdür: yeniden sıralanmış anahtarlar, farklı girintiler ve kaçak sondaki virgüller, neredeyse özdeş iki dosyayı hiçbir ortak noktası yokmuş gibi gösterebilir.
Bu kılavuz, temiz ve güvenilir bir diff elde etmek için izlenecek adımları açıklar. JSON dosyalarının anlamsal olarak aynı kalırken kağıt üzerinde neden birbirinden uzaklaştığını, bilmeye değer birkaç yöntemi ve birlikte takip edebileceğiniz çalışmalı bir örneği ele alacağız. Sadece aracı istiyorsanız, JSON karşılaştırma sayfamız tüm bunları tarayıcıda yapar.
JSON dosyalarını karşılaştırmanın neden aldatıcı derecede zor olduğu
JSON, küçük ve katı bir dilbilgisine sahiptir (bkz. json.org adresindeki spec), ancak yazarlara metnin nasıl düzenleneceği konusunda çok fazla özgürlük tanır. İki dosya tamamen aynı nesneyi tanımlayabilir ve yine de bayt bayt farklı olabilir. Düz metin diff'i bunların hiçbirini bilmez, bu yüzden hepsini özenle işaretler.
Başlamadan önce içselleştirilmesi gereken şey şudur: JSON'da nesne
anahtarlarının sırası yoktur. Spec
(RFC 8259)
bir nesneyi sırasız ad/değer çiftleri kümesi olarak tanımlar. Dolayısıyla
{"name":"Ada","id":7} ve {"id":7,"name":"Ada"}
eşittir; satır diff'i onları kırmızı ve yeşil renklerle boyasa bile.
| Diff'te gördüğünüz | Gerçek bir değişiklik mi? | Ne yapmalı |
|---|---|---|
| Farklı sıradaki anahtarlar | Hayır, nesneler sırasızdır | Her iki taraftaki anahtarları sırala |
| 2 boşluk vs 4 boşluk girinti | Hayır | Her iki tarafı aynı şekilde biçimlendir |
| Küçültülmüş vs güzel yazdırılmış | Hayır | Her iki tarafı biçimlendir |
| Dosya sonundaki sondaki yeni satır | Hayır | Yoksay veya boşlukları kırp |
"7" değerinin 7 olarak değişmesi | Evet, dize vs sayı | Araştır, bu gerçek bir değişiklik |
| Farklı sıradaki dizi öğeleri | Belki, diziler sıralıdır | Sıralamanın burada önemli olup olmadığına karar ver |
Son satır insanları şaşırtır. Diziler sırasını korur, nesneler korumaz.
Dolayısıyla [1, 2, 3] ve [3, 2, 1] gerçekten
farklıdır, ancak bir nesnenin içindeki anahtarlar serbestçe yer değiştirebilir.
JavaScript'in tüm bunları nasıl ayrıştırdığına dair ayrıntıları öğrenmek
isteyenler için MDN'de kapsamlı bir
JSON nesnesi referansı
bulunmaktadır.
JSON karşılaştırmanın dört yolu ve her birine ne zaman başvurulacağı
Tek bir en iyi yöntem yoktur. Dosyaların nerede bulunduğuna ve ne öğrenmek istediğinize bağlıdır. İşte yaygın seçeneklerin kıyaslaması.
| Yöntem | En iyi kullanım | Çaba | JSON'ı anlıyor mu? |
|---|---|---|---|
| Göz gezdirme | Küçük dosyalar, bir veya iki alan | Düşük | Hayır, ayrıştırıcı sizsiniz |
| Çevrimiçi diff aracı | Hızlı kontroller, her yerden yapıştırma | Düşük | Biçimlendir + anahtarları sırala ile evet |
Komut satırı (jq, diff) | Diskteki dosyalar, betik yazma, büyük dosyalar | Orta | Önce sıralarsanız evet |
IDE veya git diff | Bir repodaki dosyalar | Commit'lendiyse düşük | Varsayılan olarak satır tabanlı |
Çoğu kişi için bir tarayıcı aracı hız açısından kazanır çünkü kurulacak hiçbir şey yoktur ve bir log veya API çağrısından doğrudan kod parçacığı yapıştırabilirsiniz. Sorun biçimlendirme gürültüsüdür; bununla bir sonraki adımda ilgileneceğiz. Terminalde yaşıyorsanız, jq öğrenilmesi gereken araçtır ve önemli olan tek bayrağı göstereceğiz.
En hızlı temiz karşılaştırma, adım adım
Biri bana iki yapılandırma dosyası verip "ne farklı?" diye sorduğunda kullandığım rutin budur. Yaklaşık on beş saniye sürer.
- JSON karşılaştırma aracını açın.
- Orijinali sola, yeni sürümü sağa yapıştırın.
- Her iki tarafta da Biçimlendir'e tıklayarak aynı girinti stilini paylaşmalarını sağlayın.
- Anahtarları sırala (kanonikleştir) seçeneğini etkinleştirerek yeniden sıralanmış anahtarların değişiklik olarak görünmesini durdurun.
- Sonucu okuyun. Yeşil eklenmiş, kırmızı kaldırılmış demektir; değişen bir değer her birinden birer tane olarak gösterilir.
Üçüncü ve dördüncü adımlar tüm hilenin özüdür. Her iki dosya da aynı biçimde biçimlendirildiğinde ve anahtarları sıralandığında, vurgulanacak tek şey gerçekten değişen şeydir. Diff motorumuz Google'ın diff-match-patch üzerine inşa edilmiştir; önce satır satır karşılaştırır, bu sayede uzun dosyalarda bile hızlı kalır.
Çalışmalı bir örnek
Diyelim ki bir kullanıcı kaydındaki değişikliği inceliyorsunuz. İşte öncesi:
{
"name": "Ada Lovelace",
"role": "editor",
"active": true,
"seats": 3
}
Ve işte sonrası, bir ekip arkadaşının size ilettiği şekliyle:
{
"active": true,
"name": "Ada Lovelace",
"role": "admin",
"seats": 5,
"team": "platform"
}
Bunları ham bir satır diff'ine bırakın; anahtarlar farklı sırada olduğundan neredeyse her satır taşınmış gibi görünür. Her ikisini biçimlendirin ve sıralayın, gerçek hikaye kısadır:
| Alan | Önce | Sonra | Değişiklik |
|---|---|---|---|
role | editor | admin | Değiştirildi |
seats | 3 | 5 | Değiştirildi |
team | — | platform | Eklendi |
name | Ada Lovelace | Ada Lovelace | Değişiklik yok |
active | true | true | Değişiklik yok (sadece taşındı) |
Üç gerçek düzenleme: bir rol yükseltmesi, bir koltuk sayısı ve yeni bir
ekip alanı. Yeniden sıralama gürültüydü. editor'dan
admin'e bu terfi, incelemede yakalamak istediğiniz türden bir
şeydir ve yirmi satır yanlış pozitifin altına gömüldüğünde gözden kaçması
kolaydır.
Komut satırında biçimlendirme gürültüsünü gidermek
Dosyalarınız zaten diskteyse, aynı "biçimlendir ve sırala" fikri iki kısa
komutla çalışır. -S bayrağı jq'ya nesne anahtarlarını
sıralamasını söyler; her ikisini de bu şekilde aktararak normalize etmek,
düz diff'in dürüst olmasını sağlar:
jq -S . old.json > old.sorted.json
jq -S . new.json > new.sorted.json
diff old.sorted.json new.sorted.json
Artık diff yalnızca gerçekten değişen değerleri raporlar;
çünkü her iki dosya da aynı girinti ve aynı anahtar sırasına sahiptir.
Bu, tarayıcıda Biçimlendir ve anahtarları sırala seçeneğini tıklamanın
terminal karşılığıdır.
Metin diff'i ve yapısal diff karşılaştırması
Yukarıdakilerin tümü metin diff'idir: hızlı, görsel ve değişikliği
okuyan bir insan için mükemmeldir. Yapısal diff daha ileri gider
ve değişikliği veri olarak tanımlar. Bunun standardı,
RFC 6902'de
tanımlanan JSON Patch'tir; düzenlemeleri belirli bir yolda replace
ve add gibi işlemler olarak ifade eder. Değişikliği yalnızca
bir kişinin görmesi değil, bir programın uygulaması gerektiğinde yapısal
diff'e ihtiyaç duyarsınız. Günlük inceleme için, sıralanmış anahtarlara
sahip bir metin diff'i fazlasıyla yeterlidir.
Dikkat edilmesi gereken yaygın tuzaklar
| Tuzak | Neden ısırır | Çözüm |
|---|---|---|
| Sayı hassasiyeti | 2^53 − 1 üzerindeki tam sayılar JavaScript'te hassasiyetini yitirir | Büyük ID'leri dize olarak karşılaştırın; bkz. MAX_SAFE_INTEGER |
| Unicode kaçışları | "café" ve "café" aynı dizedir, farklı baytlar | Her iki tarafı biçimlendirin; bu kodlamayı normalleştirir |
| Yinelenen anahtarlar | Çoğu ayrıştırıcı sessizce sonuncuyu tutar | Diff'e güvenmeden önce JSON'ı doğrulayın |
| Sondaki virgüller | Geçerli JSON değil; bir dosya hiç ayrıştırılamayabilir | Önce sözdizimini düzeltin, doğrulayıcı bunu işaretleyecektir |
| Dize vs sayı | "5" ve 5 benzer görünür ama farklı türlerdir | Bu gerçek bir değişikliktir, görmezden gelmeyin |
İlgili araçlar
JSON nadiren uğraştığınız tek biçimdir. Ortamlar arasında yapılandırmayı karşılaştırıyorsanız, YAML karşılaştırma aynı fikri YAML'a uygular. İki API çağrısı arasındaki değişiklikleri incelemek için API yanıt diff'i aracı yapılmıştır ve bağımlılık güncellemelerini okumak package.json diff sayfasında en kolaydır.
Sıkça sorulan sorular
- JSON dosyalarını çevrimiçi karşılaştırmak onları bir yere yüklüyor mu?
- comparetext.org'da diff tarayıcınızda çalışır. İki JSON dosyası kendi makinenizdeki JavaScript tarafından karşılaştırılır, bu nedenle Kaydet veya Paylaş'a açıkça tıklamadığınız sürece hiçbir şey sunucuya gönderilmez. Bu onu yapılandırma dosyaları, API yanıtları ve her tuş vuruşunda yükleyen rastgele bir web sitesine yapıştırmak istemeyeceğiniz diğer veriler için güvenli kılar.
- Neden iki JSON dosyam her satırı farklı gösteriyor?
- Neredeyse her zaman biçimlendirmedir, gerçek değişiklikler değil. Bir dosya küçültülmüş veya sekmelerle girintili, diğeri iki boşlukla girintili ya da nesne anahtarları farklı sırada olabilir. Her iki tarafta da Biçimlendir'e tıklayarak aynı girintiyi kullanmalarını sağlayın, ardından anahtarları sıralayın; böylece sıra önemli olmaktan çıkar. Bundan sonra diff genellikle gerçekten değişen değerlerin küçük bir kısmına indirgenir.
- Anahtar sırasını yoksayarak JSON'ı nasıl karşılaştırabilirim?
- JSON nesne anahtarlarının tanımlanmış bir sırası yoktur, bu nedenle
{"a":1,"b":2}ve{"b":2,"a":1}eşittir. Bir metin diff'inin de aynı fikirde olmasını sağlamak için, karşılaştırmadan önce her iki taraftaki anahtarları sıralayın. Tarayıcıda kanonikleştir (anahtarları sırala) seçeneğini kullanın. Komut satırında jq bunu yapar:jq -S . file.json. Her iki dosyanın anahtarları da aynı sıralanmış sırada olduğunda, yalnızca gerçek değer değişiklikleri görünür. - Sayfa donmadan büyük JSON dosyalarını karşılaştırabilir miyim?
- Evet, bir noktaya kadar. Satır modu diff, her karakteri karşılaştırmak yerine önce tam satırları karşılaştırdığından binlerce satırlı dosyalarda hızlı kalır. Çok büyük dosyalar (birkaç megabayt) veriyi akışa alan jq veya git diff gibi bir komut satırı aracıyla daha iyi işlenir. Tarayıcıda rahatça kaydırabildiğiniz her şey için çevrimiçi bir diff daha hızlı bir seçenektir.
- JSON'ın metin diff'i ile yapısal diff'i arasındaki fark nedir?
- Metin diff'i dosyaları satır satır karşılaştırır, tıpkı iki makaleyi karşılaştırdığı gibi. Yapısal diff JSON'ı anlar, bu nedenle yeniden sıralanmış bir anahtarın değişiklik olmadığını ve bir dizinin içinde taşınan bir değerin silinmiş artı eklenmiş değil, taşınmış olduğunu bilir. Metin diff'leri daha hızlıdır ve çoğu inceleme için yeterlidir. Yapısal diff'ler (örneğin RFC 6902'ye göre JSON Patch) bir değişikliği bir programın uygulayabileceği veri olarak tanımlamanız gerektiğinde önem kazanır.
- İki API yanıtını nasıl karşılaştırabilirim?
- Her yanıtı bir dosyaya kaydedin veya tarayıcınızın ağ sekmesinden kopyalayın, ardından eski yanıtı sola, yeni olanı sağa yapıştırın. API'nin kararlı bir sırayla döndürmediği durumlarda her ikisini de biçimlendirin ve anahtarları sıralayın. api-response-diff aracı tam olarak bunun için ayarlanmıştır: iki çağrı arasında yeniden adlandırılmış bir alanı, değişen bir durum kodunu veya dizeden sayıya dönen bir değeri fark etmek.
Denemek ister misiniz? Dosyalarınızı JSON karşılaştırma aracına yapıştırın ve nelerin değiştiğini görün.