Két JSON struktúra összehasonlítása
- Irányítópult
- Dokumentáció
- API
Miért hasonlítsunk össze két JSON-t?
Két JSON struktúra összehasonlítása gyakori feladat egy fejlesztő életében. Egy API válasz, amely frissítés után megváltozik. Egy konfigurációs fájl, amely eltér két környezet között. Egy objektumexport, amelynek igazodnia kell egy referenciához. Egy JSON diff pontosan erre a kérdésre válaszol: mi lett hozzáadva, törölve vagy módosítva, és hol?
A soronkénti diff (mint a git diff) gyakran nem elegendő. Ha a formázás eltér (szóközök, kulcsok sorrendje), a szöveges diff több száz sort jelezhet, miközben az adatszerkezet azonos. A JSON összehasonlító az elemzett szerkezeten dolgozik, ami kiküszöböli ezt a zajt és csak a szemantikai eltéréseket fedi fel.
Az eszköz által készített diff formátuma
Az eszköz minden eltérésre a következőket adja vissza:
- egy egyszerűsített JSONPath formátumú útvonalat, például:
$.user.address[0].city; - egy típust az added (hozzáadva a jobb oldalon), removed (csak a bal oldalon van jelen), modified (eltérő értékek) közül;
- a bal oldali értéket és/atau a jobb oldali értéket a típustól függően.
Az üres diff azt jelenti, hogy a két JSON szerkezetileg azonos, függetlenül a formázásuktól vagy a kulcsok sorrendjétől.
Hogyan járja be az algoritmus a két szerkezetet
Az algoritmus rekurzív. Minden szinten azonosítja a két összehasonlított érték típusát:
- Ha mindkettő asszociatív objektum, veszi a kulcsok unióját. Minden kulcsnál rekurzívan leereszkedik, vagy megjelöli mint added/removed, ha a kulcs csak az egyik oldalon létezik.
- Ha mindkettő rendezett tömb, pozíciónként hasonlítja össze őket. A tömb elején lévő különbség eltolhatja az összes többit, ami bőbeszédű diff-et eredményez: ez a naiv strukturális diff egyik ismert korlátja.
- Ha a típusok eltérnek (objektum a tömbbel szemben, skalár a null-lal szemben), az modified jelzést kap.
- Ha mindkét érték skalár (szöveg, szám, boole-érték, null), egy egyszerű szigorú összehasonlítás elegendő.
Az objektumban a kulcsok sorrendje nem számít: a {"a": 1, "b": 2} és a {"b": 2, "a": 1} üres diff-et eredményez. Ez megfelel a JSON szemantikájának, ahol a sorrend nem jelentős. Ezzel szemben a tömb elemeinek sorrendje számít: a tömb felépítéséből adódóan rendezett.
Egy konkrét példa
Íme egy felhasználói objektum két verziója:
// bal
{
"id": 42,
"name": "Alice",
"roles": ["admin", "editor"]
}
// jobb
{
"id": 42,
"name": "Alice Martin",
"roles": ["admin", "viewer"],
"active": true
}
Az elkészült diff:
$.name: modified,"Alice"→"Alice Martin"$.roles[1]: modified,"editor"→"viewer"$.active: added,true
Felhasználási esetek
- Környezetek közötti diff: egy végpont kimenetének összehasonlítása pre-produkciós és produkciós környezetben. Nagyon hasznos migráció vagy gyorsítótár-frissítés során.
- Migrációs audit: egy export összehasonlítása transzformáció előtt és után, annak ellenőrzésére, hogy nem veszett-e el mező.
- API regresszió: módosítás előtt és után összehasonlítani a választ egy azonos lekérdezésre. Az üres diff megerősíti a nem-regressziót.
- Konfigurációk szinkronizálása:
composer.jsonösszehasonlítása két ág között, két.eslintrcfájl vagy két Symfony konfiguráció összehasonlítása. - Snapshot tesztek: a soronkénti összehasonlítás helyettesítése strukturális összehasonlítással egy integrációs tesztcsomagban.
A strukturális diff korlátai
A rendezett tömbök összehasonlítása a naiv strukturális diff-ek ismert korlátja. Ha beszúrunk egy elemet a tömb elejére, az összes többi pozíció eltolódik, és a diff minden eltérést módosításként jelez. Ilyen esetekre léteznek fejlettebb algoritmusok (Myers, Patience, diff természetes kulcs alapján), de ezek kívül esnek egy általános célú összehasonlító eszköz keretein.
A diff azt sem mondja meg, hogy miért történt a változás: ez csak egy megállapítás. Egy regresszió elemzéséhez ezt a megállapítást össze kell vetni a commitokkal, a telepítésekkel és a lekérdezés paramétereivel.
JSON diff vs JSON Patch (RFC 6902)
Egy kiegészítő formátum a JSON Patch (RFC 6902). Ez műveletek
(add, remove, replace, move, copy,
test) formájában írja le, hogyan alakítható át egy JSON dokumentum egy másikká. Miközben a mi diffünk egy (emberi) megállapítás, a JSON Patch egy (gépi) recept. A két ábrázolás egyszerű esetekben egyenértékű, és a JSON Patch hasznos a részleges módosításokat elfogadó RESTful API-khoz.
Gyakori kérdések
Függ a diff a kulcsok sorrendjétől?
Nem: egy JSON objektum esetében a sorrend nem jelentős. Az összehasonlító ugyanazt az eredményt adja, függetlenül attól, hogy a kulcsok rendezettek-e vagy sem.
Hogyan kezeljük azokat a tömböket, ahol a sorrend nem fontos?
Az eszköz alapértelmezés szerint rendezettként kezeli a tömböket (ez a JSON szemantikája). Ha halmazokat kezel, hasonlítás előtt rendezze mindkét tömböt egy természetes kulcs szerint, vagy használjon olyan speciális összehasonlító szolgáltatást, amely figyelembe veszi ezt a szemantikát.
Mi a különbség a Git diff-hez képest?
A Git szövegsorokat hasonlít össze. Ha a behúzás vagy a kulcsok sorrendje eltér, a Git diff nagyon bőbeszédű. A JSON diff az elemzett szerkezeten dolgozik, és csak az adatbeli eltéréseket jelzi.
Elfogadja az érvénytelen JSON-t?
Nem: ha a két JSON egyike nem elemezhető, az eszköz hibát jelez. Először ellenőrizze a JSON validátorunkkal.
Kérés példa
curl -X POST https://cdrn.fr/api/v1/tools/json-diff/execute \
-H "Content-Type: application/json" \
-d '{"left":"...","right":"..."}'
Bemeneti séma
| Mező | Típus | Kötelező | Alapértelmezett |
|---|---|---|---|
left |
text | ✓ | – |
right |
text | ✓ | – |
Végpontok
GET https://cdrn.fr/api/v1/tools- listázza az összes elérhető eszköztGET https://cdrn.fr/api/v1/tools/json-diff- lekéri ezen eszköz sémájátPOST https://cdrn.fr/api/v1/tools/json-diff/execute- végrehajtja ezen eszközt JSON payloaddal