ToolHub
View All Posts

Przewodnik zapytań JSONPath: Jak przeszukiwać dane JSON

JSON stał się uniwersalnym językiem sieci Web. API zwracają JSON, pliki konfiguracyjne używają JSON, bazy danych przechowują dokumenty JSON. Ale w miarę jak struktury JSON stają się większe i głębiej zagnieżdżone, znajdowanie określonych wartości staje się coraz trudniejsze. Tutaj wchodzi JSONPath. JSONPath to język zapytań, który pozwala nawigować i wyodrębniać dane z dokumentów JSON za pomocą zwięzłych wyrażeń ścieżkowych, podobnie jak XPath robi to dla XML. Ten przewodnik obejmuje wszystko, od podstawowej składni po zaawansowane filtrowanie, z praktycznymi przykładami, które możesz zastosować od razu.

Czym jest JSONPath?

JSONPath to język zapytań JSON, pierwotnie zaproponowany przez Stefana Goessnera w 2007 roku. Oferuje zwartą składnię do wybierania węzłów z dokumentu JSON, podobnie jak selektory CSS lokalizują elementy HTML lub wyrażenia XPath lokalizują węzły XML. Zamiast pisać pętle i logikę warunkową do przeglądania struktury JSON, po prostu piszesz wyrażenie opisujące ścieżkę do pożądanych danych.

Wyrażenia JSONPath zaczynają się od węzła głównego dokumentu JSON i nawigują przez obiekty i tablice do pożądanych wartości. Język obsługuje symbole wieloznaczne, zejście rekurencyjne, wycinki tablic i wyrażenia filtrujące, co jest wystarczające dla większości potrzeb ekstrakcji danych.

Przykładowy dokument JSON

W tym przewodniku użyjemy następującego dokumentu JSON jako przykładu roboczego. Jest to klasyczny przykład z oryginalnej propozycji JSONPath z dodatkowymi danymi:

{
  "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
    }
  }
}

Referencja składni JSONPath

JSONPath używa niewielkiego zestawu operatorów, które łączą się, tworząc potężne zapytania. Oto kompletna referencja składni:

OperatorOpisPrzykład
$Węzeł główny dokumentu$
.Operator dziecka (dostęp do właściwości obiektu)$.store
[]Indeks tablicy lub operator dziecka$.store.book[0]
[*]Symbol wieloznaczny dla wszystkich elementów tablicy$.store.book[*]
..Zejście rekurencyjne (przeszukuje wszystkie poziomy)$..author
.keyNazwane właściwości obiektu$.store.bicycle
['key']Notacja nawiasowa dla dostępu do właściwości$['store']['book']
[start:end]Wycinanie tablicy (indeks końcowy wyłączony)$.store.book[0:2]
[?()]Wyrażenia filtrujące< 10)]
()Wyrażenia skryptowe (zależne od implementacji)$.store.book[(@.length-1)]

Podstawowe wyrażenia JSONPath

Dostęp do węzła głównego i bezpośrednich dzieci

Znak dolara $ reprezentuje węzeł główny dokumentu JSON. Stamtąd używasz notacji kropkowej, aby uzyskać dostęp do właściwości obiektu, i notacji nawiasowej, aby uzyskać dostęp do indeksów tablicy.

WyrażenieWynik
$Cały dokument JSON
$.storeobiekt store (zawierający tablicę book i obiekt bicycle)
$.store.bicycle{"color": "red", "price": 19.95}
$.store.bicycle.color"red"
$.store.bookCała tablica book
$.store.book[0]Pierwszy obiekt książki
$.store.book[0].title"Sayings of the Century"
$.store.book[3].author"J.R.R. Tolkien"

Notacja nawiasowa

Notacja nawiasowa jest alternatywą dla notacji kropkowej, przydatną, gdy nazwy właściwości zawierają znaki specjalne, spacje lub zaczynają się od cyfr:

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

Notacja nawiasowa i notacja kropkowa są wymienne dla właściwości obiektów. Jednak notacja nawiasowa musi być używana, gdy nazwa właściwości jest dynamiczna lub zawiera znaki, które są nieprawidłowe w notacji kropkowej.

Operator wieloznaczny

Operator wieloznaczny * dopasowuje wszystkie elementy w tablicy lub wszystkie właściwości w obiekcie. Jest niezwykle przydatny do wyodrębniania wszystkich wartości na danym poziomie bez znajomości konkretnych kluczy lub indeksów.

WyrażenieWynik
$.store.*Wszystkie wartości w obiekcie store (tablica book i obiekt bicycle)
$.store.book[*]Wszystkie książki w tablicy (wszystkie cztery obiekty book)
$.store.book[*].authorWszystkie nazwiska autorów: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
$.store.*.pricecena bicycle i tablica book (nie cena pojedynczej książki)

Zejście rekurencyjne: operator podwójnej kropki

Operator podwójnej kropki .. jest jedną z najpotężniejszych funkcji JSONPath. Przeszukuje każdy poziom drzewa JSON w poszukiwaniu określonego klucza, nie tylko bezpośrednich dzieci. Pomyśl o tym jak o głębokim wyszukiwaniu w całym dokumencie.

WyrażenieWynik
$..authorWartości author we wszystkich miejscach dokumentu
$..priceWszystkie wartości price: [8.95, 12.99, 8.99, 22.99, 19.95]
$..book[2]Trzecia książka, wyszukiwanie rekurencyjne
$..categoryWszystkie wartości category: ["reference", "fiction", "fiction", "fiction"]

Operator zejścia rekurencyjnego jest szczególnie przydatny, gdy nie znasz dokładnej ścieżki do żądanych danych lub gdy ten sam klucz pojawia się na wielu poziomach zagnieżdżenia. Na przykład, jeśli odpowiedź API zawiera pole id na różnych poziomach zagnieżdżenia, $..id zbierze wszystkie id.

Wycinanie tablicy

Wycinanie tablicy pozwala wybrać zakres elementów z tablicy. Składnia [start:end] wybiera elementy od indeksu początkowego do (ale nie włączając) indeksu końcowego. Obsługiwane są indeksy dodatnie i ujemne.

WyrażenieWynik
$.store.book[0:2]Pierwsze dwie książki (indeksy 0 i 1)
$.store.book[1:3]Druga i trzecia książka (indeksy 1 i 2)
$.store.book[-1]Ostatnia książka (The Lord of the Rings)
$.store.book[-2:]Dwie ostatnie książki
$.store.book[:2]Pierwsze dwie książki (tak samo jak [0:2])
$.store.book[2:]Trzecia książka i kolejne

Uwaga: zachowanie wycinania może się nieznacznie różnić między implementacjami JSONPath. Powyższa składnia jest zgodna z konwencją używaną przez większość popularnych bibliotek i standard IETF RFC 9535.

Wyrażenia filtrujące

Wyrażenia filtrujące są miejscem, gdzie JSONPath naprawdę staje się potężny. Pozwalają wybierać elementy na podstawie warunków, a nie pozycji. Składnia filtrowania używa [?(warunek)], gdzie warunek jest oceniany dla każdego elementu.

Operatory porównania

JSONPath obsługuje następujące operatory porównania w wyrażeniach filtrujących:

OperatorZnaczeniePrzykład
==Równy[?(@.category == "fiction")]
!=Nierówny[?(@.category != "fiction")]
<Mniejszy niż< 10)]
<=Mniejszy lub równy<= 8.99)]
>Większy niż[?(@.price > 15)]
>=Większy lub równy[?(@.price >= 12.99)]
=~Dopasowanie wyrażeń regularnych (częściowa implementacja)[?(@.author =~ /Tolkien/i)]

Praktyczne przykłady filtrowania

Korzystając z naszego przykładowego dokumentu, oto praktyczne wyrażenia filtrujące i ich wyniki:

Find all books cheaper than $10:

< 10)]

Zwraca książki "Sayings of the Century" (8,95 USD) i "Moby Dick" (8,99 USD).

Find all fiction books:

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

Zwraca trzy książki: "Sword of Honour", "Moby Dick" i "The Lord of the Rings".

Find books with an ISBN:

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

Zwraca książki, które mają właściwość isbn: "Moby Dick" i "The Lord of the Rings". Dzieje się tak, ponieważ filtr sprawdza, czy właściwość istnieje.

Find the most expensive book:

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

Zwraca "The Lord of the Rings" (22,99 USD).

Operatory logiczne w filtrach

Możesz łączyć warunki za pomocą operatorów logicznych:

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

Pierwsze wyrażenie znajduje książki beletrystyczne poniżej 10 USD (tylko "Moby Dick"). Drugie znajduje książki powyżej 15 USD lub należące do kategorii referencyjnej (zwraca "Sayings of the Century" i "The Lord of the Rings").

JSONPath a XPath

JSONPath jest wyraźnie wzorowany na XPath, a oba języki mają wiele podobieństw koncepcyjnych. Jeśli znasz przetwarzanie XML, zrozumienie tej relacji może być pomocne.

FunkcjaJSONPathXPath
Symbol pierwiastka$/
Dostęp do dzieci.key lub ['key']/element
Indeksowanie tablicy[0][1] (zaczynając od 1)
Symbol wieloznaczny**
Zejście rekurencyjne..//
Filtrowanie[?(condition)][condition]
WłaściwośćNie dotyczy (JSON nie ma atrybutów)@attr
Bieżący węzeł@ (w filtrach). lub current()
RodzicNieobsługiwane..
Nieobsługiwane13 osi (ancestor, following itp.)
Model danychObiekty i tabliceElementy, atrybuty, węzły tekstowe

Kluczowa różnica polega na tym, że XPath operuje na bogatym modelu drzewa z elementami, atrybutami, węzłami tekstowymi, przestrzeniami nazw i instrukcjami przetwarzania. JSONPath operuje na prostszym modelu obiektów (map klucz-wartość) i tablic (uporządkowanych list). Ta prostota sprawia, że JSONPath jest łatwiejszy do nauki, ale mniej ekspresyjny niż XPath w złożonych zapytaniach.

JSONPath w praktyce

Testowanie API

JSONPath jest niezbędny do testowania API. Gdy wysyłasz żądanie do API i otrzymujesz dużą odpowiedź JSON, JSONPath pozwala na asercję określonych wartości bez ręcznego nawigowania po całej strukturze. Większość narzędzi do testowania API natywnie obsługuje JSONPath.

Na przykład w testach możesz zweryfikować, że cena pierwszej książki jest poniżej 10 dolarów:

// 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"]

Transformacja danych

Podczas integracji systemów używających różnych formatów danych JSONPath pomaga wyodrębniać i przekształcać określone pola. Możesz wyodrębnić wartości z jednej struktury JSON i mapować je na inną bez pisania złożonego kodu przechodzenia.

Zarządzanie konfiguracją

Złożone pliki konfiguracyjne często zawierają głęboko zagnieżdżony JSON. JSONPath pozwala wysyłać zapytania o konkretne wartości konfiguracyjne bez ładowania i parsowania całej struktury. Narzędzia takie jak jq używają składni podobnej do JSONPath do przetwarzania JSON w potokach wiersza poleceń.

Monitorowanie i alerty

W systemach obserwowalności zapytania JSONPath mogą wyodrębniać metryki z logów i odpowiedzi API w formacie JSON. Możesz skonfigurować alerty, które wyzwalają się, gdy zapytanie JSONPath zwraca wartości przekraczające próg.

Implementacje JSONPath

JSONPath jest dostępny w prawie każdym języku programowania. Oto najpopularniejsze biblioteki:

JęzykBibliotekiInstalacja
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

Przykład 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

Wskazówka: podczas pracy ze złożonymi wyrażeniami JSONPath buduj je stopniowo. Zacznij od prostej ścieżki, takiej jak $.store, zweryfikuj, że działa, a następnie stopniowo rozszerzaj: $.store.book, potem $.store.book[*], potem $.store.book[*].price, a na końcu dodaj filtry. To ułatwia debugowanie.

Typowe pułapki i wskazówki

W 2024 roku IETF opublikował RFC 9535, formalnie standaryzując JSONPath. Specyfikacja rozwiązuje wiele niejasności i niespójności między implementacjami. Kluczowe aspekty standardu obejmują:

Jeśli zaczynasz nowy projekt, preferuj biblioteki implementujące RFC 9535 dla maksymalnej kompatybilności i przewidywalnego zachowania.

Potrzebujesz szybko wyszukać dane JSON? Wypróbuj nasz darmowy tester JSONPath online, który ocenia wyrażenia na twoich dokumentach JSON w czasie rzeczywistym.

Wypróbuj wyszukiwarkę JSONPath

Standard IETF: RFC 9535

Przykład Python

JSONPath to język zapytań JSON, podobny do XPath dla XML. Używa wyrażeń ścieżkowych do nawigacji i wyodrębniania określonych wartości z dokumentów JSON. Wyrażenia JSONPath, takie jak $.store.book[0].title, pozwalają precyzyjnie lokalizować dane w złożonych, zagnieżdżonych strukturach JSON bez potrzeby pisania niestandardowego kodu parsowania.

Czym jest JSONPath?

JSONPath jest zaprojektowany dla struktur obiektów i tablic JSON, podczas gdy XPath jest zaprojektowany dla drzew elementów i atrybutów XML. JSONPath używa $ jako węzła głównego, notacji kropkowej do dostępu do obiektów i notacji nawiasowej do dostępu do tablic. XPath używa / do separacji ścieżek i @ do dostępu do atrybutów. JSONPath jest prostszy, ale mniej bogaty w funkcje niż XPath.

Czym różni się JSONPath od XPath?

Podwójna kropka (..) w JSONPath to operator zejścia rekurencyjnego. Przeszukuje wszystkie poziomy struktury JSON w poszukiwaniu nazwanego klucza, nie tylko bezpośrednie węzły potomne. Na przykład $..author znajduje wszystkie klucze author w dowolnym miejscu całego dokumentu, niezależnie od głębokości zagnieżdżenia.

Co oznacza podwójna kropka (..) w JSONPath?

<, ><=, >< 10)] znajduje wszystkie książki poniżej 10 dolarów.

Czy JSONPath może filtrować dane na podstawie warunków?

JSONPath został pierwotnie zaproponowany przez Stefana Goessnera w 2007 roku bez formalnej specyfikacji, co prowadziło do różnic między implementacjami. W 2024 roku IETF opublikował RFC 9535, formalnie standaryzując JSONPath. Nowoczesne implementacje zbliżają się do tego standardu, ale niektóre starsze biblioteki mogą nadal mieć niewielkie różnice składniowe.