JSON Toolkit

Výběr nástroje pro JSON diff: textový diff, strukturální diff a vizualizace

Shrnutí: Textový diff najde, kde se soubory liší; strukturální diff rozhoduje, zda jsou obsahy ekvivalentní. Volba správné vrstvy zabrání tomu, aby se pořadí klíčů považovalo za incident.

Středně pokročilý~9 min čteníPublikováno 2026-10-31Aktualizováno 2026-10-31
Titulní obrázek článku Výběr nástroje pro JSON diff

Stručně: textový diff objevuje změnu (nejprve seřaďte klíče pomocí jq -S), strukturální diff rozhoduje o ekvivalenci (pole seřaďte podle primárního klíče) a vizualizace změnu pouze vysvětluje nebo reviduje; tři vrstvy udržujte v CI oddělené.

Dva JSON dokumenty, které vypadají odlišně, nemusí mít odlišný obsah. Než zvolíte nástroj, zvolte správnou vrstvu srovnání.

1. Tři druhy „diffu“ nejsou totéž

Mnoho týmů považuje „srovnat JSON“ za jednu činnost a poté v různých scénářích naráží na stejné problémy. Pomáhá oddělit tři vrstvy:

Vrstva Co se srovnává Co odhaluje Typické použití
Textový diff Surové bajty a řádky Odsazení, pořadí klíčů, mezery, zalomení řádků Rozdíly v konfiguraci, revize kódu
Strukturální diff Parsované objekty a pole Přidané nebo odebrané klíče, změněné hodnoty, změny prvků pole Regrese API, migrace dat
Vizuální diff Jak jsou rozdíly prezentovány Do které úrovně změna patří, jak velký má dopad Lidská revize, týmová diskuse

Textový diff je bez závislostí, rychlý a přirozeně se integruje s Git. Jeho slabinou je, že nezná sémantiku JSON. Dva zcela ekvivalentní dokumenty se rozsvítí červeně a zeleně, pokud se liší pořadí klíčů nebo odsazení. Strukturální diff je opak: nejprve parsuje a poté srovnává, takže rozpozná, že se hodnota jen přesunula. Potřebuje však správnou strategii zarovnání polí; jinak se jedno vložení přečte jako úplný přepis.

Vizualizace není třetí algoritmus. Vykresluje výstup ostatních dvou vrstev, aby člověk rychle potvrdil, zda je rozdíl očekávaný. Je dobrá pro lidský úsudek a špatná jako náhrada automatizovaných kontrol. Smíchání vrstev obvykle vede k CI pipeline, která je trvale červená, a k týmu, který se naučil ji ignorovat.

2. Textový diff: nejprve ukliďte pořadí klíčů pomocí jq -S

Pro rychlý pohled na dva soubory je nejlevnější kombinací jq -S plus diff -u. Přepínač -S rekurzivně seřadí klíče objektů a normalizuje dokumenty, jejichž obsah je shodný, ale pořadí klíčů odlišné:

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

Tím se odstraní nejčastější falešný poplach. RFC 8259 definuje objekty jako neuspořádané kolekce, takže {"a":1,"b":2} a {"b":2,"a":1} jsou stejná hodnota. Textový diff však označí každý řádek jako změněný. Seřazení předem posune červené bloky mnohem blíž skutečným problémům.

Pozor, jq -S řadí jen klíče; neřadí pole. Pořadí pole má v JSON význam a [1,2] není stejná hodnota jako [2,1], takže nástroj toto rozhodnutí neudělá za vás. Pokud je pole konceptuálně neuspořádaná množina, seřaďte ho podle primárního klíče sami, než ho srovnáte.

Je tu ještě jeden detail, který stojí za zapamatování: diff skončí s kódem 1, když najde rozdíly, ale chybějící soubor nebo chyba oprávnění také produkuje nenulový kód. V CI nepovažujte každý nenulový kód za „obsah se změnil“, jinak se překlep v cestě ohlásí jako změna dat. Bezpečnější vzor nejprve ověří soubory a poté řeší rozdíl:

if ! diff -u a.sorted.json b.sorted.json; then
  echo "Obsah JSON se liší" >&2
  exit 1
fi

delta dělá textový diff čitelným

Surový výstup diff -u funguje, ale dlouhé řádky a hluboce vnořený JSON se čtou únavně. delta je filtr diffu, který přidává zvýrazňování syntaxe, čísla řádků a jasnější barvy pozadí:

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

Začínal jako pager pro Git, takže umí převzít i git diff. Pro lidi, kteří denně čtou deset konfiguračních diffů, takové nástroje zlepšují rychlost čtení, nikoli algoritmickou přesnost. Další běžnou volbou je git diff --no-index --word-diff, který srovnává na úrovni slov a dobře funguje pro zminifikovaný JSON uložený na velmi dlouhých řádcích.

Jedno varování: zkrášlení neodstraňuje falešné rozdíly. Pokud pořadí klíčů nebylo normalizováno, delta jen udělá šum hezčím. Správné pořadí je vždy nejprve normalizovat, poté zdobit.

3. Strukturální diff: jsondiffpatch rozumí sémantice

Když je otázkou, zda jsou dvě data sémanticky ekvivalentní, použijte strukturální diff. Nejběžnější volbou v ekosystému JavaScriptu je jsondiffpatch, který vrací delta objekt popisující změny, nikoli textové řádky se značkami + a -:

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 rozlišuje přidané klíče, odebrané klíče, nahrazené hodnoty a přesunuté prvky pole. To znamená, že deltu můžete procházet přímo v assertionech: undefined, když není rozdíl, nebo popis cestu po cestě, když je. Na rozdíl od textového diffu ho neruší odsazení, pořadí klíčů ani číselný zápis jako 1e3 versus 1000.

Stejně důležité je, že výstup strukturálního diffu může živit pracovní postup s patchi. jsondiffpatch poskytuje patch a reverse, takže delta lze aplikovat na původní objekt a později vrátit. Jedno upozornění: automaticky vygenerovaná delta nemá stejný formát jako ručně psaný JSON Patch a převod mezi nimi něco stojí. Širšímu přístupu ke srovnávání se věnuje Diff a srovnávání JSON.

4. Jak odstranit falešné rozdíly způsobené pořadím klíčů

Pořadí klíčů není jen otravné; může vést ke špatným závěrům. Při vyšetřování postupujte ve třech krocích:

  1. Před srovnáním rekurzivně normalizujte pořadí klíčů pomocí jq -S nebo ekvivalentu.
  2. Odstraňte pole, která se mění při každém běhu, například timestamp, requestId a traceId.
  3. Potvrďte, že neexistují duplicitní klíče. Duplicitní klíče se během parsování vyřeší pravidlem „poslední vyhrává“, takže textový diff je vidí, zatímco strukturální ne.
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

Tento postup se dobře hodí pro rozdíly v konfiguraci. Prožeňte staging i produkci stejnou normalizací a co zůstane, je rozdíl, který skutečně potřebuje vysvětlení. Pravidla filtru udržujte ve verzovaném skriptu, místo abyste je znovu psali zpaměti. Editační a skriptovací části nástrojového řetězce se věnuje Editory, příkazový řádek a automatizace.

5. Pole: zarovnat podle indexu, nebo podle id?

Pole jsou nejchybovější částí srovnávání JSON. Při výchozím zarovnání podle indexu vložení jednoho záznamu na začátek posune všechny následující prvky a nástroj je označí jako změněné. Nástroj není rozbitý; strategie zarovnání je špatná.

Zarovnání Funguje, když Přednost Riziko
Podle indexu Pořadí pole nese obchodní význam Jednoduché, nevyžaduje další pole Jedno vložení způsobí kaskádové falešné poplachy
Podle primárního klíče Prvky jsou množina s jedinečným id Detekuje vložení, smazání a přesuny Vyžaduje stabilní jedinečný klíč
Nejdelší společná podposloupnost Pořadí je důležité, ale vložení jsou povolena Robustnější než čisté indexování Hůř vysvětlitelné, vyšší náklady

jsondiffpatch používá objectHash k deklaraci primárního klíče a indexuje prvky pole před srovnáním:

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

S prostým jq můžete nejprve seřadit a poté použít textový diff:

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

Kompromis u zarovnání podle id je, že změny pozice se už nepočítají jako rozdíly. Pokud obchod potřebuje vědět, že se záznam přesunul z pozice 2 na pozici 5, srovnávejte také explicitní pole pořadí; nespoléhejte jen na obsah množiny.

6. Vizuální diff: vrstva postavená pro lidi

Výstup strukturálního diffu je navržen pro stroje, nikoli pro porady. Když potřebujete někomu jinému vysvětlit změnu, vizualizace je účinnější:

  • Diff editor ve VS Code se hodí pro revizi soubor po souboru, s panely vedle sebe a inline zvýrazněním.
  • Stromové prohlížeče jako JSON Crack a JSON Hero ukazují, do které úrovně změna patří.
  • jsondiffpatch obsahuje HTML formatter, který vykreslí deltu jako sbalitelný bohatý náhled.

Hodnotou vizualizace je kontext. Textový diff říká, že se změnil řádek 88; stromové zobrazení říká, že řádek 88 patří do data.items[3].price. Vizualizace však obvykle načítá celý dokument do prohlížeče nebo desktopové aplikace. Než otevřete produkční payload, ověřte, zda nástroj počítá lokálně, nebo nahrává na server.

7. Tři zásady pro zařazení diffu do CI

Za prvé, normalizujte před srovnáním. Zafixujte odsazení, rekurzivně seřaďte klíče a odfiltrujte volatilní pole dřív, než se diff spustí. Jinak CI opakovaně selhává na šumu.

Za druhé, volte zarovnání podle sémantiky. Pokud je pole množinou, zarovnávejte podle primárního klíče. Pokud je posloupností, ponechte zarovnání podle indexu. Neaplikujte jedno pravidlo na každé API.

Za třetí, tvrdte hodnoty, nikoli text. Srovnávání parsovaných objektů v testech je mnohem stabilnější než srovnávání výstupu JSON.stringify. Když kontrola selže, vypište cestu rozdílu a hodnoty před a po, místo abyste do logu vysypali celý payload.

# Vypište jen lišící se cesty a hodnoty, nikoli celý dokument
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

Pokud rozdíl vyžaduje dlouhodobé sledování, committed normalizační skript a očekávaný soubor společně. Pokud jde o jednorázové vyšetřování, dočasný skript poté smažte, aby se tiše nestal druhou implementací obchodní logiky.

8. Tabulka výběru nástroje

Scénář První volba Alternativa Klíčové připomenutí
Občasné srovnání souborů diff ve VS Code diff -u Nejprve naformátujte, abyste odstranili šum
Rozdíly v konfiguraci jq -S + diff delta Filtrujte volatilní pole
Regrese odpovědí API jsondiffpatch deepdiff Pole zarovnejte podle primárního klíče
Vysvětlení změny týmu JSON Crack / JSON Hero HTML formatter Ověřte, zda se data nahrávají
Velmi velké soubory extrakce podstromu pomocí jq prohlížení v jless Nenačítejte celý strom do paměti
Kontrola před commitem git diff --no-index pre-commit Explicitně ošetřete návratové kódy

Neexistuje jediný nejlepší nástroj pro JSON diff; existuje jen správný nástroj pro aktuální vrstvu. Textový diff objevuje změnu, strukturální diff soudí ekvivalenci a vizualizace změnu vysvětluje. Udržovat tři vrstvy oddělené je mnohem spolehlivější než hledat jeden nástroj, který dělá všechno. Řešením konfliktů napříč větvemi se pokračuje v článku JSON a sloučení v Git.

Časté dotazy

Mění jq -S také pořadí pole?

Ne. -S řadí jen klíče objektů a pole ponechává v původním pořadí. Pole jsou v JSON uspořádaná, takže nástroj nezmění [1,2] na [2,1]. Pokud je pole konceptuálně neuspořádaná množina, seřaďte ho explicitně pomocí sort_by.

Jsou 1 a 1.0 ve strukturálním diffu stejná hodnota?

Většina parserů obě převede na stejné číslo, takže strukturální diff je obvykle považuje za rovné, zatímco textový diff je označí jako rozdílné. Strukturální diff používejte k rozhodnutí o ekvivalenci a textový diff k rozhodnutí, zda jsou soubory bajtově identické.

Lze výstup diffu použít přímo jako JSON Patch?

Ne přímo. Nástroj diffu hlásí, co se liší, zatímco JSON Patch popisuje uspořádaný seznam operací; formáty a sémantika se liší. Automaticky vygenerované patche navíc obvykle odkazují na indexy polí, které při souběžnosti zastarají. Před aplikací přidejte operaci test.

Jak srovnávat JSON soubory o velikosti desítek MB?

Nejprve extrahujte podstrom, který vás zajímá, například pomocí jq '.data.items', poté seřaďte podle primárního klíče a srovnejte. Nenačítejte celý strom do paměti pro rekurzivní diff. Velmi velké soubory se lépe zpracovávají streamováním nebo dávkovým srovnáváním a paměťové náklady vyžadují samostatné posouzení.

Mohou online nástroje pro diff uniknout moje data?

Záleží na implementaci. Čistě frontendové nástroje počítají v prohlížeči a data nenahrávají; serverově vykreslované nástroje posílají obsah na backend, kde se může dostat do logů. Než srovnáte produkční konfiguraci nebo zákaznická data, ověřte, že stránka počítá lokálně, a v případě potřeby to otestujte jednou s odpojenou sítí.

Jak se rozhodnout mezi textovým a strukturálním diffem?

Pro rychlý pohled, kde se dva soubory liší, seřaďte klíče pomocí jq -S a spusťte diff -u. K rozhodnutí, zda jsou dva dokumenty sémanticky ekvivalentní, použijte strukturální diff, například jsondiffpatch, a pole zarovnejte podle primárního klíče. Textový diff je bez závislostí a integruje se s Git, zatímco strukturální diff neruší odsazení, pořadí klíčů ani číselný zápis.

Proč by CI nemělo považovat každý nenulový návratový kód diffu za rozdíl?

diff skončí s 1, když najde rozdíly, ale chybějící soubor nebo chyba oprávnění také vrací nenulový kód. Považovat každý nenulový kód za „obsah se změnil“ ohlásí překlep v cestě jako změnu dat. Bezpečnější vzor nejprve ověří soubory a poté rozdíl řeší zvlášť.

Mám srovnávat soubory o desítkách MB v prohlížeči?

Ne. Nejprve extrahujte podstrom, který vás zajímá, pomocí jq, poté seřaďte podle primárního klíče a srovnejte. Načtení celého stromu do paměti pro rekurzivní diff stojí mnohem více paměti a času. Velmi velké soubory se lépe zpracovávají streamováním nebo dávkovým srovnáváním.