JSON è diventato di fatto lo standard per lo scambio di dati sul web. API, servizi Web e siti Web moderni utilizzano ampiamente JSON per l'invio di dati tra server e client.
Ad esempio, secondo BuiltWith, oltre il 70% dei 10,000 siti Web principali utilizza API JSON. Il formato JSON è facile da generare e analizzare in qualsiasi linguaggio di programmazione.
Tuttavia, estrarre in modo efficiente informazioni significative da documenti JSON di grandi dimensioni può ancora essere difficile. È qui che entra in gioco JSONPath: un linguaggio di query specializzato per semplificare il modo in cui individuare e trasformare i dati JSON.
Il problema con l'analisi JSON
Tradizionalmente, i dati JSON vengono elaborati nelle applicazioni analizzandoli completamente in strutture dati native come i dict Python. Analizzeresti l'intera risposta JSON anche se avessi bisogno solo di un piccolo sottoinsieme di dati.
Questo approccio presenta alcuni svantaggi:
- Rallentamento delle prestazioni – L'analisi di file JSON di grandi dimensioni in oggetti è computazionalmente costosa
- Elevato utilizzo della memoria – L'intera struttura JSON deve essere mantenuta in memoria
- Codice dettagliato – Spesso è necessario scrivere molto codice di loop/attraversamento per scavare negli oggetti analizzati
Un'alternativa è utilizzare le espressioni regolari per estrarre direttamente i frammenti JSON corrispondenti. Tuttavia, le espressioni regolari diventano disordinate con complesse strutture nidificate. Ha anche problemi con nomi di chiavi dinamici o profondità di nidificazione arbitrarie.
JSONPath fornisce un modo più chiaro e conciso per eseguire query su JSON rispetto all'analisi non elaborata o alla corrispondenza regex.
Presentazione di JSONPath
Le espressioni JSONPath descrivono come accedere a parti di un documento JSON. È concettualmente simile a XPath che consente di interrogare elementi e attributi in XML:
//node/child::* - XPath for all child nodes
$.node.child - Equivalent JSONPath
Alcuni vantaggi dell'approccio JSONPath:
- leggibilità – Le espressioni di query sono facili da comprendere
- concisione – Non è necessario un codice di attraversamento dettagliato
- Flessibilità – Supporta ricerche, filtri, corrispondenze con caratteri jolly
- Prestazione – Algoritmi di corrispondenza molto ottimizzati
- Scalabilità – Può elaborare rapidamente anche documenti JSON di grandi dimensioni
JSONPath fornisce un'alternativa semplice e scalabile per l'estrazione dei dati da JSON. Successivamente esaminiamo come funziona.
Interrogazione di JSON con JSONPath
Un'espressione JSONPath è una stringa che descrive come individuare i valori all'interno di una struttura JSON. Per esempio:
data = {
"store": {
"books": [
{ "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
}
]
}
}
# All book titles
books = jsonpath(data, ‘$.store.books[*].title‘)
# Filter fiction books
fiction_books = jsonpath(data, ‘$.store.books[?(@.category=="fiction")].title‘)
JSONPath utilizza operatori come:
.
– Operatore bambino[]
– Operatore di pedice per l'accesso all'array*
– Carattere jolly per tutti gli elementi corrispondenti?()
– Filtraggio dei predicati
Concatenarli insieme consente di eseguire query in modo efficiente in JSON complessi:
# Get all authors of books over 10 dollars
authors = jsonpath(data, ‘$.store.books[?(@.price > 10)].author‘)
Niente più codice di loop annidato in profondità! JSONPath abbina gli oggetti direttamente senza la necessità di analizzare completamente l'intero albero JSON.
Operatori JSONPath disponibili
Ecco un riepilogo degli operatori disponibili in JSONPath:
Operatori di percorso
$
– Oggetto radice@
– Oggetto corrente.
or[]
– Operatore bambino..
– Cerca ricorsivamente i discendenti
Operatori di filtro
[?(<expression>)]
– Filtra oggetti[(<condition>)]
– Filtra in base alla condizione
Operatori di matrice
*
– Il carattere jolly indicizza tutti gli elementi[<index>]
– Posizione dell'indice[start:end]
– Porzione di array[?(<condition>)]
– Filtro
Operatori per la proiezione
[]
– Proiezione – Estrae le proprietà elencate[@]
– Proiezione dell'indice – Appiattisce gli array
Altri operatori
|
– Operatore sindacale()
– Operatore prioritario,
– Delimita più risultati
Questi ti offrono un'ampia flessibilità per eseguire query, filtrare e trasformare i dati JSON utilizzando semplici stringhe di percorso.
JSONPath e XPath per XML
Poiché JSONPath condivide molte somiglianze con XPath, vale la pena confrontare i due:
XPath
- Linguaggio di query per XML
- Consente di attraversare l'albero XML
- Supporta assi avanzati come
//
,/*
,//@
- Utilizzare per estrarre i nodi XML
Percorso JSON
- Linguaggio di query equivalente per JSON
- Sintassi ispirata a XPath
- La sintassi più semplice poiché JSON è rappresentativamente più semplice di XML
- Implementazione rapida poiché non è necessaria l'analisi XML
Entrambi consentono di selezionare nodi in strutture di dati gerarchiche. JSONPath potrebbe essere considerata una versione semplificata di XPath specializzata per JSON anziché XML.
Librerie JSONPath popolari per Python
JSONPath è stato implementato per molti linguaggi di programmazione. Alcune librerie popolari per Python sono:
Biblioteca | Descrizione |
---|---|
jsonpath-ng | Libreria consigliata, veloce con funzionalità avanzate |
jsonpath-rw | Implementazione di riferimento conforme |
jsonpath | Implementazione semplice ma funzionalità limitate |
Per la maggior parte degli usi, jsonpath-ng
fornisce la migliore combinazione di conformità, funzionalità e prestazioni.
Vediamo come utilizzarlo in modo più dettagliato.
Interrogazioni e filtri con jsonpath-ng
Innanzitutto, installa jsonpath-ng:
pip install jsonpath-ng
Importare:
from jsonpath_ng import jsonpath, parse
Qualche esempio:
data = { "name": "John",
"age": 30,
"cars": [
{ "model": "BMW", "year": 2019 },
{ "model": "Tesla", "year": 2020 }
]
}
# Extract name
name = jsonpath(data, ‘$.name‘)
# Get first car
first_car = jsonpath(data, ‘$.cars[0]‘)
# Filter Tesla cars
teslas = jsonpath(data, ‘$.cars[?(@.model=="Tesla")]‘)
# Get all car years
years = jsonpath(data, ‘$..cars[*].year‘)
È inoltre possibile utilizzare il parse()
metodo che compila il percorso per prestazioni migliori:
parser = parse(‘$.cars[*].year‘)
for obj in json_data:
years = parser.find(obj)
print(years)
Funziona più velocemente quando si applica lo stesso percorso a più documenti JSON.
Filtraggio dei dati JSON
Una delle funzionalità più potenti di JSONPath è la sua sintassi di filtro.
I filtri consentono di selezionare oggetti che corrispondono a criteri specifici. Per esempio:
RecentCars = jsonpath(data, ‘$.cars[?(@.year > 2015)]‘)
Questo rende le auto più nuove del 2015.
Puoi filtrare utilizzando confronti come:
- Matematico:
=
,!=
,>
,<=
, ecc. - Logico:
and
,or
,not
- Espressioni regolari:
=~
,!=~
- Esistenza:
exists()
,?()
I filtri possono anche essere combinati:
ElectricCars = jsonpath(data,
‘$.cars[?(@.year > 2010 && @.model =~ "Tesla|Volt")]`
)
Ciò consentirà di produrre auto elettriche dopo il 2010.
Trasformazione dei dati JSON
Oltre a estrarre i dati, JSONPath può trasformare oggetti JSON utilizzando operatori come:
[]
– Proiezione per rimodellare gli oggetti[@]
– Indicizzazione degli array da appiattire
Ad esempio, appiattindo i dati dell'auto in un semplice elenco:
all_models = jsonpath(data, ‘$..cars[*].model‘)
all_years = jsonpath(data, ‘$..cars[*].@year‘)
I @
esegue proiezioni basate su indici.
Il concatenamento di filtri, proiezioni e sezioni consente di ristrutturare JSON a livello di codice.
Funzionalità avanzate di jsonpath-ng
Alcune funzionalità avanzate aggiuntive fornite da jsonpath-ng:
Funzioni personalizzate
Puoi registrare funzioni personalizzate per estendere JSONPath:
def format_price(x):
return f‘${x:,.2f}‘
jsonpath.register_custom_function(format_price, ‘format‘)
prices = jsonpath(data, ‘$.prices[*].format(@)‘)
Ciò consente di implementare trasformazioni di dati complesse direttamente all'interno delle espressioni JSONPath.
Caching e ottimizzazione
jsonpath-ng compila e ottimizza le query per le prestazioni. Supporta anche:
- Memorizzazione nella cache per la velocità
- Corrispondenza pigra per evitare scansioni non necessarie
- Ottimizzazione della resa in uscita
Quindi funziona bene anche con enormi documenti JSON.
Operatori aggiuntivi
Alcuni altri operatori utili:
?()
– Verifica dell'esistenza=~
,!=~
– Corrispondenza regexin
– Contiene assegnoall
– Quantificatore universale
Metodi JSONPath
Metodi di supporto come:
find()
– Restituisce le corrispondenzeparse()
– Compila il percorso
Fornire un'API più semplice per le query comuni.
Utilizzo di JSONPath per il Web Scraping
Una delle applicazioni più utili di JSONPath è l'estrazione dei dati durante il web scraping.
I siti Web moderni fanno molto affidamento su JSON per la trasmissione dei dati:
- API – JSON è il formato standard per le API REST
- Dati asincroni – JSON viene utilizzato con JavaScript per gli aggiornamenti dinamici delle pagine
- Metadati della pagina – Dati del sito spesso archiviati in script come JSON
Analizzare manualmente tutto questo JSON sarebbe complicato. JSONPath consente di eseguire facilmente query solo sui frammenti necessari.
Ad esempio, ecco come estrarre i dati di prodotto da una pagina di e-commerce:
import requests
from jsonpath_ng import jsonpath, parse
# Fetch product page
url = "http://www.example.com/product/123"
response = requests.get(url)
# Extract JSON data
data = response.json()
# Parse out product details
name = jsonpath(data, ‘$.product.name‘)[0]
price = jsonpath(data, ‘$.product.price‘)[0]
image = jsonpath(data, ‘$.product.images[0]‘)
print(name, price, image)
La chiave sta nell'utilizzare JSONPath per acquisire direttamente solo i campi necessari invece dell'elaborazione manuale.
Ecco alcuni casi d'uso comuni:
- Raschiamento API – Estrai i dati dalle risposte dell'API REST
- Siti JavaScript – Interrogare gli oggetti utilizzati dai frontend
- applicazioni mobili – Analizza i dati JSON dal traffico dell'app
- Contenuto dinamico – Crea set di dati da JavaScript lato client
JSONPath consente lo scraping scalabile di migliaia di documenti JSON con semplici stringhe di percorso.
Analisi di file JSON di grandi dimensioni
Anche se JSONPath si adatta bene, l'analisi di enormi documenti JSON può ancora presentare sfide:
- Utilizzo della memoria – Caricamento dell'intero JSON in memoria
- Carico della CPU – L'analisi di documenti complessi richiede un uso intensivo del processore
- Trasferimento in rete – Documenti di grandi dimensioni significano più larghezza di banda
Alcuni suggerimenti quando si lavora con dati JSON di grandi dimensioni:
- Utilizza parser di streaming per evitare il caricamento completo di JSON
- Compila percorsi con
parse()
invece di ripetere l'analisi - Estrai solo i campi effettivamente necessari invece degli oggetti completi
- Usa il
laziness
per evitare scansioni di oggetti non necessarie - Esegui su potenti server cloud quando gestisci dati su scala TB+
- Distribuisci l'analisi tra i cluster per l'elaborazione parallela
Nella maggior parte dei casi, JSONPath può estrarre in modo efficiente i dati anche da file JSON di grandi dimensioni con centinaia di migliaia di record se ottimizzato correttamente.
Perché mi piace usare JSONPath
In qualità di ingegnere proxy esperto che lavora ampiamente con i dati JSON, ecco perché adoro utilizzare JSONPath:
- Sintassi concisa – Le espressioni del percorso sono meravigliosamente concise rispetto al codice di analisi tradizionale
- Produttività incrementata – Puoi interrogare JSON con la stessa facilità con cui interroga un database grazie alla sintassi intuitiva
- Filtraggio robusto – I filtri dei predicati semplificano la selezione dei dati corrispondenti
- Prestazioni incredibilmente veloci – jsonpath-ng utilizza algoritmi estremamente ottimizzati che consentono un'estrazione dei dati rapidissima anche su set di dati di grandi dimensioni
- Memoria efficiente – Poiché analizza JSON in modo selettivo, l'impronta di memoria è bassa rispetto all'analisi completa in oggetti nativi
- Potenza di web scraping – La facile estrazione dei dati dalle API e dalle risposte JavaScript è il punto in cui JSONPath brilla
Sebbene strumenti come jq e grep siano ottimi, trovo che JSONPath sia più semplice ed elegante per la maggior parte delle mie esigenze di analisi JSON. Il supporto dell'ecosistema Python con librerie come jsonpath-ng lo rende la mia scelta preferita per affettare e tagliare i dati JSON.
Supporto JSONPath in altre lingue
Anche se ci siamo concentrati su Python, JSONPath è disponibile in molti linguaggi di programmazione:
- JavaScript - Percorso JSON Plus
- PHP - Percorso JSON
- Go - gjson
- PostgreSQL - Percorso JSON
- R - jsonpath
Poiché JSON è un formato di dati universale, è utile poterlo interrogare in modo efficiente da qualsiasi lingua. Per fortuna JSONPath è ampiamente supportato.
Perché JSONPath è importante
JSON è diventato rapidamente essenziale per API Web, microservizi e applicazioni front-end. JSONPath porta funzionalità di query simili a XPath nel mondo dei dati JSON.
Avere un linguaggio di percorso standardizzato per estrarre facilmente valori JSON nidificati presenta molti vantaggi:
- Semplifica l'estrazione dei dati JSON su piattaforme e linguaggi diversi
- Fornisce un'alternativa leggibile alla brutta analisi delle espressioni regolari
- Abilita il web scraping scalabile senza la necessità di analizzare intere risposte
- Consente trasformazioni complesse utilizzando proiezioni e filtri
- Sblocca la capacità di interrogare in modo efficiente enormi set di dati JSON
- Si adatta naturalmente alle pipeline insieme ad altri strumenti JSON come jq
Poiché JSON continua a dominare come formato di interscambio di dati di fatto, disporre di un set di operatori JSONPath comuni aiuterà a domare la complessità della navigazione di documenti JSON di grandi dimensioni.
Conclusione
JSONPath fornisce un modo elegante per estrarre e trasformare valori dai dati JSON tramite espressioni di percorso concise.
Biblioteche come jsonpath-ng
semplifica l'integrazione di JSONPath nei tuoi progetti Python.
Le prelibatezze chiave:
- JSONPath consente di eseguire facilmente query nelle strutture JSON utilizzando "." e gli operatori '[]'
- Il filtraggio in base ai valori delle proprietà utilizzando i predicati è ben dimensionato
- Le trasformazioni possono essere applicate utilizzando proiezioni ed espansione di array
- JSONPath evita la necessità di analizzare interi oggetti JSON durante lo scraping
- La sintassi è modellata sulle espressioni XPath per eseguire query su XML
- Supportato in molti linguaggi di programmazione
Per lavorare con servizi Web basati su JSON, JSONPath è uno strumento indispensabile per il toolkit di qualsiasi sviluppatore. JSONPath ti consente di porre domande semplici e ottenere solo i dati di cui hai bisogno da documenti JSON complessi.