Twee JSON-bestanden vergelijken en wijzigingen vinden

De snelste manier om twee JSON-bestanden te vergelijken is beide in een naast-elkaar-diff-tool te plakken, ze op dezelfde manier te formatteren en de gemarkeerde regels te lezen. Het moeilijke deel is meestal niet het vergelijken zelf. Het is het ruis: opnieuw geordende sleutels, verschillende inspringing en losse afsluitende komma's kunnen ervoor zorgen dat twee bijna identieke bestanden lijken niets gemeen te hebben.

Deze gids legt uit hoe u een schone, betrouwbare diff krijgt. We kijken naar waarom JSON-bestanden op papier uit elkaar drijven terwijl ze inhoudelijk hetzelfde blijven, de handvol methoden die het waard zijn te kennen, en een uitgewerkt voorbeeld dat u kunt volgen. Als u gewoon de tool wilt, doet onze JSON-vergelijkingspagina dit alles in de browser.

Waarom JSON-bestanden bedrieglijk moeilijk te vergelijken zijn

JSON heeft een kleine, strikte grammatica (zie de specificatie op json.org), maar geeft schrijvers veel vrijheid in hoe ze tekst opmaken. Twee bestanden kunnen hetzelfde object beschrijven en toch byte voor byte verschillen. Een gewone tekstdiff weet daar niets van, dus markeert het alles nauwgezet.

Dit is het belangrijkste om te internaliseren voordat u begint: objectsleutels in JSON hebben geen volgorde. De specificatie (RFC 8259) definieert een object als een ongeordende verzameling naam/waarde-paren. Dus {"name":"Ada","id":7} en {"id":7,"name":"Ada"} zijn gelijk, ook al kleurt een regeldiff ze rood en groen.

Ziet eruit als een wijziging, is dat meestal niet
Wat u in de diff zietIs het een echte wijziging?Wat te doen
Sleutels in een andere volgordeNee, objecten zijn ongeordendSleutels aan beide kanten sorteren
2-spatie vs. 4-spatie inspringingNeeBeide kanten hetzelfde formatteren
Geminimaliseerd vs. opgemaakNeeBeide kanten formatteren
Afsluitende nieuwe regel aan het einde van het bestandNeeNegeren of witruimte verwijderen
Een waarde veranderde van "7" naar 7Ja, string vs. getalOnderzoeken, dit is echt
Array-items in een andere volgordeMisschien, arrays zijn geordendBeslissen of volgorde hier belangrijk is

Die laatste rij verrast mensen. Arrays behouden hun volgorde, objecten niet. Dus [1, 2, 3] en [3, 2, 1] zijn echt verschillend, maar de sleutels binnen een object kunnen vrij worden herschikt. Als u de technische details wilt weten over hoe JavaScript dit alles parseert, heeft MDN een solide referentie over het JSON-object.

Vier manieren om JSON te vergelijken en wanneer u ze gebruikt

Er is geen enkele beste methode. Het hangt ervan af waar de bestanden staan en wat u wilt weten. Zo vergelijken de gangbare opties.

MethodeHet beste voorInspanningBegrijpt JSON?
Handmatig doorkijkenKleine bestanden, één of twee veldenLaagNee, u bent de parser
Online diff-toolSnelle controles, plakken van overalLaagMet opmaak + sleutels sorteren, ja
Opdrachtregel (jq, diff)Bestanden op schijf, scripting, grote bestandenGemiddeldJa, als u eerst sorteert
IDE of git diffBestanden al in een repositoryLaag als gecommitStandaard regelgebaseerd

Voor de meeste mensen wint een browsertool op snelheid omdat er niets geïnstalleerd hoeft te worden en u een fragment direct vanuit een logboek of een API-aanroep kunt plakken. Het nadeel is opmaakruis, waar we hierna mee omgaan. Als u veel in de terminal werkt, is jq de tool om te leren, en we laten de ene vlag zien die ertoe doet.

De snelste schone vergelijking, stap voor stap

Dit is de routine die ik gebruik wanneer iemand me twee configuratiebestanden geeft en vraagt "wat is er anders?" Het duurt ongeveer vijftien seconden.

  1. Open de JSON-vergelijkingstool.
  2. Plak het origineel links, de nieuwe versie rechts.
  3. Klik op Formatteren aan beide kanten zodat ze dezelfde inspringing delen.
  4. Zet sleutels sorteren (canonicaliseren) aan zodat opnieuw geordende sleutels niet meer als wijzigingen verschijnen.
  5. Lees het resultaat. Groen is toegevoegd, rood is verwijderd, en een gewijzigde waarde verschijnt als één van elk.

Stap drie en vier zijn de hele truc. Zodra beide bestanden identiek zijn opgemaakt en hun sleutels gesorteerd zijn, is het enige dat overblijft om te markeren wat er echt is veranderd. Onze diff-engine is gebouwd op Google's diff-match-patch, dat eerst regel voor regel vergelijkt zodat het snel blijft, zelfs bij lange bestanden.

Een uitgewerkt voorbeeld

Stel dat u een wijziging in een gebruikersrecord beoordeelt. Dit is de situatie van vóór:

{
  "name": "Ada Lovelace",
  "role": "editor",
  "active": true,
  "seats": 3
}

En dit is de situatie erna, zoals een teamgenoot het aanleverde:

{
  "active": true,
  "name": "Ada Lovelace",
  "role": "admin",
  "seats": 5,
  "team": "platform"
}

Gooit u die in een gewone regeldiff, dan lijkt het alsof bijna elke regel is verschoven, omdat de sleutels in een andere volgorde staan. Formatteer en sorteer beide, en het echte verhaal is kort:

Wat er echt is veranderd
VeldVoorNaWijziging
roleeditoradminGewijzigd
seats35Gewijzigd
teamplatformToegevoegd
nameAda LovelaceAda LovelaceGeen wijziging
activetruetrueGeen wijziging (alleen verplaatst)

Drie echte bewerkingen: een rolverhoging, een plaatsenaantal en een nieuw teamveld. De herordening was ruis. Die bevordering van editor naar admin is precies het soort ding dat u wilt opvangen bij de beoordeling, en het is gemakkelijk te missen wanneer het begraven ligt onder twintig regels valse positieven.

Opmaakruis op de opdrachtregel elimineren

Als uw bestanden al op schijf staan, werkt hetzelfde idee van "formatteren en sorteren" met twee korte opdrachten. De vlag -S vertelt jq om objectsleutels te sorteren; er doorheen pipen normaliseert beide bestanden zodat een gewone diff eerlijk is:

jq -S . old.json > old.sorted.json
jq -S . new.json > new.sorted.json
diff old.sorted.json new.sorted.json

Nu rapporteert diff alleen waarden die echt zijn veranderd, omdat beide bestanden dezelfde inspringing en dezelfde sleutelvolgorde hebben. Dit is het terminale equivalent van klikken op Formatteren en sleutels sorteren in de browser.

Tekstdiff vs. structurele diff

Al het bovenstaande is een tekstdiff: snel, visueel en perfect voor een mens die een wijziging leest. Een structurele diff gaat verder en beschrijft de wijziging als data. De standaard daarvoor is JSON Patch, gedefinieerd in RFC 6902, dat bewerkingen uitdrukt als operaties zoals replace en add op een bepaald pad. U wilt een structurele diff wanneer een programma de wijziging moet toepassen, niet alleen een persoon die ernaar kijkt. Voor dagelijkse beoordeling is een tekstdiff met gesorteerde sleutels meer dan voldoende.

Veelvoorkomende valkuilen om op te letten

ValkuilWaarom het toeslaatOplossing
GetalnauwkeurigheidGehele getallen boven 2^53 − 1 verliezen nauwkeurigheid in JavaScriptVergelijk grote ID's als strings; zie MAX_SAFE_INTEGER
Unicode-escapes"café" en "café" zijn dezelfde string, verschillende bytesFormatteer beide kanten, wat de codering normaliseert
Dubbele sleutelsDe meeste parsers bewaren de laatste stilletjesValideer de JSON voordat u de diff vertrouwt
Afsluitende komma'sGeen geldige JSON; één bestand kan mogelijk helemaal niet worden geparseerdHerstel eerst de syntaxis, de validator markeert het
String vs. getal"5" en 5 zien er vergelijkbaar uit maar zijn verschillende typenDit is een echte wijziging, negeer het niet

Gerelateerde tools

JSON is zelden het enige formaat waarmee u te maken heeft. Als u configuraties tussen omgevingen vergelijkt, past YAML-vergelijking hetzelfde idee toe op YAML. Wijzigingen tussen twee API-aanroepen bekijken is precies waarvoor de API-respons diff is gebouwd, en afhankelijkheidsupdates zijn het gemakkelijkst te lezen op de pagina package.json diff.

Veelgestelde vragen

Worden JSON-bestanden online ergens geüpload bij het vergelijken?
Op comparetext.org wordt de diff in uw browser uitgevoerd. De twee JSON-bestanden worden vergeleken door JavaScript op uw eigen machine, zodat er niets naar een server wordt verzonden tenzij u expliciet op Opslaan of Delen klikt. Dat maakt het veilig voor configuratiebestanden, API-antwoorden en andere gegevens die u niet wilt plakken in een willekeurige website die bij elke toetsaanslag uploadt.
Waarom tonen mijn twee JSON-bestanden elke regel als anders?
Bijna altijd is het opmaak, niet echte wijzigingen. Het ene bestand is geminimaliseerd of ingesprongen met tabs, het andere met twee spaties, of de objectsleutels staan in een andere volgorde. Klik op Formatteren aan beide kanten zodat ze dezelfde inspringing gebruiken, sorteer dan de sleutels zodat volgorde er niet meer toe doet. Daarna krimpt de diff meestal tot de handvol waarden die echt zijn veranderd.
Hoe vergelijk ik JSON terwijl ik de sleutelvolgorde negeer?
JSON-objectsleutels hebben geen gedefinieerde volgorde, dus {"a":1,"b":2} en {"b":2,"a":1} zijn gelijk. Om een tekstdiff te laten overeenstemmen, sorteert u de sleutels aan beide kanten voor het vergelijken. In de browser gebruikt u de canonicaliseer-optie (sleutels sorteren). Op de opdrachtregel doet jq dit: jq -S . file.json. Zodra beide bestanden sleutels in dezelfde gesorteerde volgorde hebben, verschijnen alleen echte waardewijzigingen.
Kan ik grote JSON-bestanden vergelijken zonder dat de pagina vastloopt?
Ja, tot op zekere hoogte. Een regelmodus-diff blijft snel op bestanden met duizenden regels omdat het eerst hele regels vergelijkt in plaats van elk teken afzonderlijk. Zeer grote bestanden (meerdere megabytes) worden beter afgehandeld met een opdrachtregeltool zoals jq of git diff, die de gegevens streamt. Voor alles wat u comfortabel in een browser kunt doorscrollenm is een online diff de snellere optie.
Wat is het verschil tussen een tekstdiff en een structurele diff van JSON?
Een tekstdiff vergelijkt de bestanden regel voor regel, op dezelfde manier als het twee essays zou vergelijken. Een structurele diff begrijpt JSON, dus weet het dat een opnieuw geordende sleutel geen wijziging is en dat een verplaatste waarde binnen een array een verplaatsing is, niet een verwijdering plus een toevoeging. Tekstdiffs zijn sneller en goed genoeg voor de meeste beoordelingen. Structurele diffs (bijvoorbeeld JSON Patch per RFC 6902) zijn van belang wanneer u een wijziging moet beschrijven als data die een programma kan toepassen.
Hoe vergelijk ik twee API-antwoorden?
Sla elk antwoord op in een bestand of kopieer het uit het netwerktabblad van uw browser, plak dan het oude antwoord links en het nieuwe rechts. Formatteer beide zodat de inspringing overeenkomt, en sorteer sleutels als de API ze niet in een stabiele volgorde retourneert. De api-response-diff-tool is precies hierop afgestemd: een hernoemd veld, een gewijzigde statuscode of een waarde die tussen twee aanroepen van een string naar een getal is veranderd, opsporen.

Klaar om het uit te proberen? Plak uw bestanden in de JSON-vergelijkingstool en zie wat er is veranderd.