ToolHub
View All Posts

Guida alle query JSONPath: come cercare dati JSON

JSON è diventato la lingua universale del Web. Le API restituiscono JSON, i file di configurazione usano JSON, i database archiviano documenti JSON. Ma man mano che le strutture JSON diventano più grandi e più profondamente annidate, trovare valori specifici diventa sempre più difficile. È qui che entra in gioco JSONPath. JSONPath è un linguaggio di query che ti consente di navigare ed estrarre dati da documenti JSON usando espressioni di percorso concise, proprio come XPath fa per XML. Questa guida copre tutto, dalla sintassi di base ai filtri avanzati, con esempi pratici che puoi applicare immediatamente.

Cos'è JSONPath?

JSONPath è un linguaggio di query JSON originariamente proposto da Stefan Goessner nel 2007. Fornisce una sintassi compatta per selezionare nodi da documenti JSON, simile a come i selettori CSS individuano gli elementi HTML o le espressioni XPath individuano i nodi XML. Invece di scrivere cicli e logica condizionale per attraversare le strutture JSON, scrivi semplicemente un'espressione che descrive il percorso verso i dati desiderati.

Le espressioni JSONPath iniziano dal nodo radice del documento JSON e navigano attraverso oggetti e array fino ai valori desiderati. Il linguaggio supporta jolly, discesa ricorsiva, sezionamento di array ed espressioni di filtro, sufficienti per la maggior parte delle esigenze di estrazione dati.

Documento JSON di esempio

In questa guida, utilizzeremo il seguente documento JSON come esempio di lavoro. Questo è l'esempio classico della proposta originale di JSONPath, con dati aggiuntivi:

{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J.R.R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Riferimento alla sintassi JSONPath

JSONPath utilizza un piccolo insieme di operatori che si combinano per formare query potenti. Ecco il riferimento completo alla sintassi:

OperatoreDescrizioneEsempio
$Nodo radice del documento$
.Operatore figlio (accede alle proprietà dell'oggetto)$.store
[]Indice array o operatore figlio$.store.book[0]
[*]Jolly per tutti gli elementi dell'array$.store.book[*]
..Discesa ricorsiva (cerca a tutti i livelli)$..author
.keyProprietà oggetto con nome$.store.bicycle
['key']Notazione a parentesi per l'accesso alle proprietà$['store']['book']
[start:end]Sezionamento array (indice finale escluso)$.store.book[0:2]
[?()]Espressione di filtro< 10)]
()Espressione di script (dipende dall'implementazione)$.store.book[(@.length-1)]

Espressioni JSONPath di base

Accesso al nodo radice e ai figli diretti

Il simbolo del dollaro $ rappresenta il nodo radice del documento JSON. Da lì, usi la notazione a punto per accedere alle proprietà degli oggetti e la notazione a parentesi per accedere agli indici degli array.

EspressioneRisultato
$L'intero documento JSON
$.storeL'oggetto store (contiene l'array book e l'oggetto bicycle)
$.store.bicycle{"color": "red", "price": 19.95}
$.store.bicycle.color"red"
$.store.bookL'intero array book
$.store.book[0]Il primo oggetto libro
$.store.book[0].title"Sayings of the Century"
$.store.book[3].author"J.R.R. Tolkien"

Notazione a parentesi

La notazione a parentesi è un'alternativa alla notazione a punto, utile quando i nomi delle proprietà contengono caratteri speciali, spazi o iniziano con un numero:

$.store['book'][0]['title']
$['store']['bicycle']['color']

La notazione a parentesi e la notazione a punto sono intercambiabili per le proprietà degli oggetti. Tuttavia, quando il nome della proprietà è dinamico o contiene caratteri non validi nella notazione a punto, devi usare la notazione a parentesi.

Operatore jolly

L'operatore jolly * corrisponde a tutti gli elementi di un array o a tutte le proprietà di un oggetto. È estremamente utile per estrarre tutti i valori a un certo livello senza conoscere le chiavi o gli indici specifici.

EspressioneRisultato
$.store.*Tutti i valori nell'oggetto store (array book e oggetto bicycle)
$.store.book[*]Tutti i libri nell'array (tutti e quattro gli oggetti libro)
$.store.book[*].authorTutti i nomi degli autori: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
$.store.*.priceIl prezzo di bicycle e l'array book (non i prezzi dei singoli libri)

Discesa ricorsiva: l'operatore doppio punto

L'operatore doppio punto .. è una delle funzionalità più potenti di JSONPath. Cerca la chiave specificata a ogni livello dell'albero JSON, non solo nei figli diretti. Pensalo come una ricerca approfondita nell'intero documento.

EspressioneRisultato
$..authorTutti i valori author ovunque nel documento
$..priceTutti i valori price: [8.95, 12.99, 8.99, 22.99, 19.95]
$..book[2]Il terzo libro, trovato ricorsivamente
$..categoryTutti i valori category: ["reference", "fiction", "fiction", "fiction"]

L'operatore di discesa ricorsiva è particolarmente utile quando non conosci il percorso esatto dei dati desiderati, o quando la stessa chiave appare a più livelli di annidamento. Ad esempio, se una risposta API contiene campi id a vari livelli di annidamento, $..id raccoglierà tutti gli id.

Sezionamento di array

Il sezionamento di array ti consente di selezionare un intervallo di elementi da un array. La sintassi [start:end] seleziona gli elementi dall'indice iniziale fino a (ma non incluso) l'indice finale. Sono supportati sia indici positivi che negativi.

EspressioneRisultato
$.store.book[0:2]I primi due libri (indici 0 e 1)
$.store.book[1:3]Il secondo e il terzo libro (indici 1 e 2)
$.store.book[-1]L'ultimo libro (The Lord of the Rings)
$.store.book[-2:]Gli ultimi due libri
$.store.book[:2]I primi due libri (equivalente a [0:2])
$.store.book[2:]Il terzo libro e successivi

Nota che il comportamento del sezionamento può variare leggermente tra le diverse implementazioni di JSONPath. La sintassi sopra segue le convenzioni utilizzate dalla maggior parte delle librerie popolari e dallo standard IETF RFC 9535.

Espressioni di filtro

Le espressioni di filtro sono dove JSONPath diventa veramente potente. Ti consentono di selezionare elementi in base a condizioni piuttosto che alla posizione. La sintassi di filtro usa [?(condition)], dove la condizione viene valutata per ogni elemento.

Operatori di confronto

JSONPath supporta i seguenti operatori di confronto nelle espressioni di filtro:

OperatoreSignificatoEsempio
==Uguale a[?(@.category == "fiction")]
!=Diverso da[?(@.category != "fiction")]
<Minore di< 10)]
<=Minore o uguale a<= 8.99)]
>Maggiore di[?(@.price > 15)]
>=Maggiore o uguale a[?(@.price >= 12.99)]
=~Corrispondenza regex (implementazione parziale)[?(@.author =~ /Tolkien/i)]

Esempi pratici di filtro

Utilizzando il nostro documento di esempio, ecco espressioni di filtro pratiche e i loro risultati:

Find all books cheaper than $10:

< 10)]

Restituisce i libri "Sayings of the Century" ($8.95) e "Moby Dick" ($8.99).

Find all fiction books:

$.store.book[?(@.category == "fiction")]

Restituisce tre libri: "Sword of Honour", "Moby Dick" e "The Lord of the Rings".

Find books with an ISBN:

$.store.book[?(@.isbn)]

Restituisce i libri che hanno una proprietà isbn: "Moby Dick" e "The Lord of the Rings". Questo perché il filtro verifica l'esistenza della proprietà.

Find the most expensive book:

$.store.book[?(@.price > 20)]

Restituisce "The Lord of the Rings" ($22.99).

Operatori logici nei filtri

Puoi combinare condizioni usando operatori logici:

< 10 && @.category == "fiction")]
$.store.book[?(@.price > 15 || @.category == "reference")]

La prima espressione trova libri di narrativa sotto i $10 (solo "Moby Dick"). La seconda trova libri sopra i $15 o nella categoria reference (restituisce "Sayings of the Century" e "The Lord of the Rings").

JSONPath vs XPath

JSONPath è esplicitamente modellato su XPath, e i due linguaggi condividono molte somiglianze concettuali. Se hai familiarità con l'elaborazione XML, comprendere questa relazione è utile.

FunzionalitàJSONPathXPath
Simbolo radice$/
Accesso ai figli.key o ['key']/element
Indice array[0][1] (a base 1)
Jolly**
Discesa ricorsiva..//
Filtro[?(condition)][condition]
AttributoN/D (JSON non ha attributi)@attr
Nodo corrente@ (nei filtri). o current()
GenitoreNon supportato..
AssiNon supportati13 assi (ancestor, following, ecc.)
Modello datiOggetti e arrayElementi, attributi, nodi di testo

La differenza chiave è che XPath opera su un ricco modello ad albero con elementi, attributi, nodi di testo, namespace e istruzioni di elaborazione. JSONPath opera su un modello più semplice di oggetti (mappe chiave-valore) e array (liste ordinate). Questa semplicità rende JSONPath più facile da imparare ma meno espressivo di XPath per query complesse.

JSONPath in pratica

Test API

JSONPath è indispensabile per i test API. Quando invii una richiesta a un'API e ricevi una grande risposta JSON, JSONPath ti consente di asserire valori specifici senza navigare manualmente l'intera struttura. La maggior parte degli strumenti di test API supporta nativamente JSONPath.

Ad esempio, in un test potresti verificare che il prezzo del primo libro sia inferiore a $10:

// Using a JSONPath assertion in testing
response.jsonPath().get("store.book[0].price").should(equals(8.95));

// Find all books by a specific author
response.jsonPath().get("store.book[?(@.author == 'Herman Melville')].title");
// Returns: ["Moby Dick"]

Trasformazione dati

Quando integri sistemi che utilizzano formati di dati diversi, JSONPath aiuta a estrarre e trasformare campi specifici. Puoi estrarre valori da una struttura JSON e mapparli in un'altra senza scrivere codice di attraversamento complesso.

Gestione della configurazione

I file di configurazione complessi spesso contengono JSON profondamente annidato. JSONPath ti consente di interrogare valori di configurazione specifici senza caricare e analizzare l'intera struttura. Strumenti come jq utilizzano una sintassi simile a JSONPath per elaborare JSON nelle pipeline a riga di comando.

Monitoraggio e alerting

Nei sistemi di osservabilità, le query JSONPath possono estrarre metriche da log e risposte API in formato JSON. Puoi impostare avvisi che si attivano quando una query JSONPath restituisce un valore che supera una soglia.

Implementazioni JSONPath

JSONPath è disponibile in quasi tutti i linguaggi di programmazione. Ecco le librerie più popolari:

LinguaggioLibreriaInstallazione
JavaScriptjsonpath-plusnpm install jsonpath-plus
Pythonjsonpath-ngpip install jsonpath-ng
JavaJsonPath (Jayway)Maven: com.jayway.jsonpath
C#Json.NET (Newtonsoft)NuGet: Newtonsoft.Json
Gogjsongo get github.com/tidwall/gjson
PHPjsonpathcomposer require softcreatr/jsonpath
Rubyjsonpathgem install jsonpath

Esempio JavaScript

< 10)]',
  json: data
});
// Returns books with price < 10

Python Example

from jsonpath_ng import parse

data = { /* our sample JSON */ }

# Find all authors
author_expr = parse('$..author')
authors = [match.value for match in author_expr.find(data)]
# ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]

# Find cheap books
cheap_expr = parse('$.store.book[?(@.price < 10)]')
cheap_books = [match.value for match in cheap_expr.find(data)]

Common Pitfalls and Tips

Suggerimento: quando lavori con espressioni JSONPath complesse, costruiscile passo dopo passo. Inizia con un percorso semplice come $.store, verifica che funzioni, poi espandi gradualmente: $.store.book, poi $.store.book[*], poi $.store.book[*].price e infine aggiungi i filtri. Questo rende il debug più semplice.

Insidie e consigli comuni

Nel 2024, l'IETF ha pubblicato RFC 9535, standardizzando formalmente JSONPath. La specifica risolve molte ambiguità e incoerenze che esistevano tra le implementazioni. Gli aspetti chiave dello standard includono:

Se stai iniziando un nuovo progetto, preferisci librerie che implementano RFC 9535 per la massima compatibilità e comportamento prevedibile.

Hai bisogno di interrogare rapidamente dati JSON? Prova il nostro tester JSONPath online gratuito per valutare le espressioni in tempo reale sui tuoi documenti JSON.

Prova il cercatore JSONPath

Standard IETF: RFC 9535

Esempio Python

JSONPath è un linguaggio di query JSON, simile a XPath per XML. Utilizza espressioni di percorso per navigare ed estrarre valori specifici dai documenti JSON. Un'espressione JSONPath come $.store.book[0].title ti consente di individuare dati in complesse strutture JSON annidate senza scrivere codice di parsing personalizzato.

Cos'è JSONPath?

JSONPath è progettato per la struttura a oggetti e array di JSON, mentre XPath è progettato per l'albero di elementi e attributi di XML. JSONPath usa $ come nodo radice, la notazione a punto per accedere agli oggetti e la notazione a parentesi per accedere agli array. XPath usa / per la separazione del percorso e @ per accedere agli attributi. JSONPath è più semplice ma meno ricco di funzionalità di XPath.

In cosa JSONPath differisce da XPath?

Il doppio punto (..) in JSONPath è l'operatore di discesa ricorsiva. Cerca la chiave nominata a tutti i livelli della struttura JSON, non solo nei figli diretti. Ad esempio, $..author trova tutte le chiavi author ovunque nel documento, indipendentemente da quanto profondamente siano annidate.

Cosa significa il doppio punto (..) in JSONPath?

<, ><=, >< 10)] trova tutti i libri sotto i $10.

JSONPath può filtrare i dati in base a condizioni?

JSONPath è stato originariamente proposto da Stefan Goessner nel 2007 senza una specifica formale, portando a variazioni tra le implementazioni. Nel 2024, l'IETF ha pubblicato RFC 9535 standardizzando formalmente JSONPath. Le implementazioni moderne stanno convergendo su questo standard, ma alcune librerie più vecchie potrebbero ancora avere lievi differenze di sintassi.