Sia il puntatore JSON che JSONPath affrontano posizioni all'interno di un documento JSON, e
appaiono entrambi nei stessi tipi di strumenti: $ref in JSON Schema, operazioni
PATCH, differenze basate su percorsi. Risolvono problemi diversi, e sapere quale
di essi un dato compito richiede effettivamente evita di scegliere lo strumento sbagliato.
Puntatore JSON: una posizione, RFC 6901
Un puntatore e una sequenza di token separati da /: /user/name significa la
chiave name dentro l'oggetto user, /items/0 significa il primo elemento del
vettore items. Due caratteri necessitano di essere escape all'interno di un token (~1 per un
/ letterale, ~0 per un ~ letterale), e la stringa vuota come puntatore
significa l'intero documento. Questa e l'intera grammatica. Un puntatore risolve a
esattamente un valore, o fallisce, senza nulla in mezzo: non ci sono wildcard, non ci sono filtri, non c'e
modo di corrispondere a piu di una posizione che nomina.
{ "user": { "name": "Ada", "roles": ["admin", "editor"] } }
/user/name risolve a "Ada". /user/roles/1 risolve a "editor".
/user/email fallisce, perché quella chiave non esiste. Nulla nella
sintassi del puntatore puo chiedere “tutti i ruoli” in una singola espressione; il chiamante
deve gia conoscere l'indice.
JSONPath: un linguaggio di query
JSONPath, standardizzato come RFC 9535, e costruito per la corrispondenza, non solo
per l'indirizzamento. $.user.roles[*] restituisce entrambi i ruoli nell'esempio sopra in
una singola query. $..email cerca a ogni livello del documento qualsiasi chiave
chiamata email, per quanto profondamente annidata. Le espressioni di filtro come
$.items[?(@.price > 100)] selezionano elementi del vettore per una condizione sul loro
proprio contenuto. Una query JSONPath puo restituire zero corrispondenze, una, o molte, il che
e un contratto fondamentalmente diverso dal risolvi-o-fallisci di un puntatore.
La differenza pratica
Un puntatore nomina una posizione che conosci gia. Una query JSONPath descrive una condizione e lascia al motore trovare cosa la soddisfa. Questa differenza determina quale si adatta a un dato lavoro:
- Sai esattamente quale valore vuoi (“il terzo elemento del vettore dell'indirizzo di spedizione”): usa un puntatore. E piu semplice, ha un significato unico per documento, e tutte le implementazioni concordano su cosa fa, dato che la RFC lascia poca differenza per differenze di dialetto.
- Stai cercando valori che corrispondono a una condizione, o non conosci
il percorso esatto in anticipo (“ogni oggetto con un
statusdifailed, ovunque appaia”): rivolgiti a JSONPath. E qui le differenze di dialetto iniziano a contare: le implementazioni di JSONPath variano piu di quanto suggeriscono gli stessi esempi della RFC 9535, quindi una query scritta per una libreria non e garantita di comportarsi in modo identico in un'altra.
Dove ognuno appare nella pratica
Le operazioni JSON Patch (RFC 6902) usano esclusivamente puntatori; ogni "path"
in un'operazione add, remove, replace o move e un puntatore JSON,
perché un'operazione di patch punta a una posizione esatta per progetto. La parola
chiave $ref di JSON Schema risolve anch'essa tramite la sintassi del puntatore, per lo stesso
motivo: un riferimento di schema punta a una definizione, non a un insieme di esse.
JSONPath appare dove una persona o uno strumento deve interrogare un documento
interattivamente: debuggando una grande risposta API, estraendo un campo dai
log, o costruendo una regola che deve corrispondere a qualsiasi documento con una
data forma indipendentemente da dove si trova il campo pertinente.
Provare entrambi
L'Valutatore di Puntatore JSON risolve un puntatore contro un documento e, in caso di ricerca fallita, riporta dove si e fermato e quali chiavi esistono effettivamente a quel punto, invece di un semplice “non trovato”. Il Tester JSONPath esegue il sottoinsieme documentato della RFC 9535 con estensioni di funzioni, e la scheda JSONPath di questo blog ha un esempio elaborato per ogni selettore che vale la pena conoscere. Come usare il puntatore JSON tratta la sintassi del puntatore in maggior dettaglio, escape inclusi.