Twee JSON-structuren vergelijken
- Dashboard
- Documentatie
- API
Waarom twee JSON's vergelijken?
Het vergelijken van twee JSON-structuren komt regelmatig voor in het leven van een ontwikkelaar. Een API-antwoord dat verandert na een update. Een configuratiebestand dat afwijkt tussen twee omgevingen. Een objectexport die moet uitlijnen met een referentie. Een JSON-diff beantwoordt deze vraag precies: wat is toegevoegd, verwijderd of gewijzigd, en waar?
Een regel-voor-regel diff (à la git diff) volstaat vaak niet. Als de opmaak
verschilt (spaties, sleutelvolgorde), signaleert de tekstuele diff honderden regels terwijl de datastructuur
identiek is. Een JSON-comparator werkt op de structuur eenmaal geparseerd, wat deze ruis elimineert en
alleen de semantische afwijkingen onthult.
Het formaat van de door de tool geproduceerde diff
Voor elke afwijking geeft de tool terug:
- een pad in vereenvoudigd JSONPath-formaat, bijvoorbeeld
$.user.address[0].city; - een type onder added (toegevoegd aan rechts), removed (alleen aanwezig aan links), modified (verschillende waarden);
- de waarde van links en/of de waarde van rechts afhankelijk van het type.
Een lege diff betekent dat de twee JSON's structureel identiek zijn, onafhankelijk van hun opmaak of de volgorde van de sleutels.
Hoe het algoritme de twee structuren doorloopt
Het algoritme is recursief. Op elk niveau identificeert het het type van de twee vergeleken waarden:
- Als beide associatieve objecten zijn, neemt het de unie van de sleutels. Voor elke sleutel daalt het recursief af, of markeert het added/removed als de sleutel slechts aan één kant bestaat.
- Als beide geordende arrays zijn, vergelijkt het positie per positie. Een verschil aan het begin van de array kan al de rest verschuiven, wat een uitgebreide diff produceert: het is een geaccepteerde limiet van de naïeve structurele diff.
- Als de types verschillen (object versus array, scalair versus null), wordt het gemarkeerd modified.
- Als beide waarden scalairen zijn (tekenreeks, getal, boolean, null), volstaat een eenvoudige strikte vergelijking.
De volgorde van de sleutels in een object telt niet: {"a": 1, "b": 2} en {"b": 2, "a": 1}
produceren een lege diff. Dat is in overeenstemming met de JSON-semantiek, waar de volgorde niet significant is. Daarentegen
telt de volgorde van de elementen van een array: een array is geordend door constructie.
Een concreet voorbeeld
Hier zijn twee versies van een gebruikersobject:
// gauche
{
"id": 42,
"name": "Alice",
"roles": ["admin", "editor"]
}
// droite
{
"id": 42,
"name": "Alice Martin",
"roles": ["admin", "viewer"],
"active": true
}
De geproduceerde diff:
$.name: modified,"Alice"→"Alice Martin"$.roles[1]: modified,"editor"→"viewer"$.active: added,true
Gebruiksgevallen
- Omgevingsdiff: de uitvoer van een endpoint in pre-productie en in productie vergelijken. Zeer nuttig tijdens een migratie of een cacheverversing.
- Migratie-audit: een export voor en na transformatie vergelijken om te verifiëren dat geen enkel veld verloren is gegaan.
- API-regressie: voor en na een wijziging het antwoord vergelijken voor een identieke vraag. Een lege diff bevestigt het ontbreken van regressie.
- Configuratie-synchronisatie:
composer.jsonvergelijken tussen twee branches, twee.eslintrc-bestanden, twee Symfony-configuraties. - Snapshot tests: een regel-voor-regel vergelijking vervangen door een structurele vergelijking in een suite van integratietests.
Limieten van de structurele diff
Het vergelijken van geordende arrays is een bekende limiet van naïeve structurele diffs. Als men een element aan het begin van de array invoegt, worden alle volgende posities verschoven en signaleert de diff elke afwijking als een wijziging. Voor dergelijke gevallen bestaan er geavanceerdere algoritmen (Myers, Patience, diff per natuurlijke sleutel), maar deze vallen buiten het kader van een generalistische vergelijkingstool.
De diff zegt ook niet waarom een verandering heeft plaatsgevonden: het is een vaststelling. Om een regressie te analyseren, moet men deze vaststelling kruisen met de commits, deployments en parameters van de aanvraag.
JSON diff vs JSON Patch (RFC 6902)
Een complementair formaat is JSON Patch (RFC 6902). Het beschrijft, in de vorm van bewerkingen
(add, remove, replace, move, copy,
test), hoe een JSON-document in een ander te transformeren. Waar onze diff een vaststelling
is (menselijk), is JSON Patch een recept (machine). De twee representaties zijn equivalent voor
eenvoudige gevallen, en JSON Patch is nuttig voor RESTful-API's die gedeeltelijke
wijzigingen accepteren.
Veelgestelde vragen
Hangt de diff af van de volgorde van de sleutels?
Nee: voor een JSON-object is de volgorde niet significant. De comparator produceert hetzelfde resultaat of de sleutels gesorteerd zijn of niet.
Hoe ga ik om met arrays waarvan de volgorde niet belangrijk is?
De tool beschouwt arrays standaard als geordend (dat is de JSON-semantiek). Als u verzamelingen verwerkt, sorteer dan beide arrays op een natuurlijke sleutel voor het vergelijken, of gebruik een gespecialiseerde vergelijkingsservice die rekening houdt met deze semantiek.
Wat is het verschil met een Git-diff?
Git vergelijkt regels tekst. Als de inspringing of sleutelvolgorde verschilt, is de Git-diff zeer uitgebreid. De JSON-diff werkt op de geparseerde structuur en signaleert alleen de gegevensafwijkingen.
Wordt een ongeldige JSON geaccepteerd?
Nee: als een van de twee JSON's niet parseert, geeft de tool een fout terug. Valideer eerst met onze JSON-validator.
Voorbeeldverzoek
curl -X POST https://cdrn.fr/api/v1/tools/json-diff/execute \
-H "Content-Type: application/json" \
-d '{"left":"...","right":"..."}'
Invoerschema
| Veld | Type | Vereist | Standaard |
|---|---|---|---|
left |
text | ✓ | – |
right |
text | ✓ | – |
Endpoints
GET https://cdrn.fr/api/v1/tools- toont alle beschikbare toolsGET https://cdrn.fr/api/v1/tools/json-diff- geeft het schema van deze tool terugPOST https://cdrn.fr/api/v1/tools/json-diff/execute- voert deze tool uit met een JSON-payload