Vad är JSONPath?
JSONPath är ett frågespråk för att extrahera värden från JSON-dokument. Det föreslogs ursprungligen av Stefan Goessner 2007 som en analog till XPath för XML, och låter dig skriva uttryck som $.store.book[*].author för att välja alla author-fält inuti en book-array utan att skriva loopar eller manuell traverseringskod. Språket standardiserades i februari 2024 som RFC 9535, publicerad av IETF.
Ett JSONPath-uttryck börjar alltid med $ som representerar roten av dokumentet. Därifrån kedjar du ihop selektorer: punktnotation för objektnycklar, hakparentesnotation för arrayindex, jokertecken för alla barn och den rekursiva nedstegningsoperatorn (..) för att söka igenom varje nivå av nästling. Filteruttryck som [?(@.price < 10)] låter dig välja element baserat på villkor utvärderade mot deras värden.
JSONPath används i API-testverktyg som Postman, observabilitetsplattformar som Datadog och Splunk, arbetsflödesmotorer som Apache NiFi, samt programmeringsbibliotek i JavaScript, Python, Go, Java och C#. Att testa dina uttryck mot verklig data innan du bäddar in dem i kod eller konfigurationsfiler förebygger tysta fel när JSON-strukturen inte matchar dina antaganden.
Varför använda denna JSONPath Tester?
Att skriva JSONPath-uttryck för hand är felbenäget. En saknad punkt, fel typ av parentes eller felaktig filtersyntax kan ge tomma resultat utan något felmeddelande. Det här verktyget ger dig omedelbar visuell återkoppling om vad ditt uttryck matchar.
JSONPath-användningsfall
JSONPath-syntaxreferens
RFC 9535 definierar standard-JSONPath-syntaxen. Tabellen nedan täcker de operatorer du kommer att använda i de flesta frågor. Alla uttryck börjar med $ (rotnoden) och kedjar en eller flera selektorer för att navigera dokumentstrukturen.
| Operator | Beskrivning | Exempel |
|---|---|---|
| $ | Root element | $.store |
| .key | Child property | $.store.book |
| [n] | Array index (zero-based) | $.store.book[0] |
| [*] | All elements in array/object | $.store.book[*] |
| .. | Recursive descent | $..author |
| [start:end] | Array slice | $.store.book[0:2] |
| [?()] | Filter expression | $.store.book[?(@.price<10)] |
| @ | Current node (inside filter) | $.store.book[?(@.isbn)] |
JSONPath vs jq vs XPath
JSONPath, jq och XPath löser samma problem (frågor mot strukturerad data) för olika format och användningsfall. JSONPath riktar sig mot JSON och är tillgängligt som ett bibliotek i de flesta språk. jq är ett fristående CLI-verktyg med sitt eget Turing-komplett filterspråk. XPath opererar på XML och är en del av W3C:s specifikationsstack.
| Funktion | JSONPath | jq | XPath |
|---|---|---|---|
| Dataformat | JSON | JSON | XML |
| Åtkomst till första elementet | $.store.book[0] | .store.book[0] | /store/book[1] |
| Rekursiv sökning | $..price | .. | .price? | //price |
| Filteruttryck | [?(@.price<10)] | select(.price < 10) | [price<10] |
| Specifikation | RFC 9535 | stedolan.github.io | W3C XPath 3.1 |
Kodexempel
Hur man utvärderar JSONPath-uttryck i populära språk och verktyg. Varje exempel använder samma JSON-struktur för en bokhandel för jämförelse.
import { JSONPath } from 'jsonpath-plus';
const data = {
store: {
book: [
{ title: 'Moby Dick', price: 8.99 },
{ title: 'The Great Gatsby', price: 12.99 }
]
}
};
// Get all book titles
JSONPath({ path: '$.store.book[*].title', json: data });
// → ['Moby Dick', 'The Great Gatsby']
// Recursive descent — find every price in the document
JSONPath({ path: '$..price', json: data });
// → [8.99, 12.99]
// Filter — books under $10
JSONPath({ path: '$.store.book[?(@.price < 10)]', json: data });
// → [{ title: 'Moby Dick', price: 8.99 }]from jsonpath_ng.ext import parse
import json
data = {
"store": {
"book": [
{"title": "Moby Dick", "price": 8.99},
{"title": "The Great Gatsby", "price": 12.99}
]
}
}
# Get all book titles
expr = parse("$.store.book[*].title")
titles = [match.value for match in expr.find(data)]
# → ['Moby Dick', 'The Great Gatsby']
# Recursive descent — all prices
expr = parse("$..price")
prices = [match.value for match in expr.find(data)]
# → [8.99, 12.99]
# Filter — books under $10
expr = parse("$.store.book[?price < 10]")
cheap = [match.value for match in expr.find(data)]
# → [{"title": "Moby Dick", "price": 8.99}]package main
import (
"fmt"
"github.com/ohler55/ojg/jp"
"github.com/ohler55/ojg/oj"
)
func main() {
src := `{
"store": {
"book": [
{"title": "Moby Dick", "price": 8.99},
{"title": "The Great Gatsby", "price": 12.99}
]
}
}`
obj, _ := oj.ParseString(src)
// Get all book titles
expr, _ := jp.ParseString("$.store.book[*].title")
results := expr.Get(obj)
fmt.Println(results)
// → [Moby Dick The Great Gatsby]
// Recursive descent — all prices
expr2, _ := jp.ParseString("$..price")
fmt.Println(expr2.Get(obj))
// → [8.99 12.99]
}# jq uses its own syntax, not JSONPath, but solves the same problem.
# Mapping common JSONPath patterns to jq:
# $.store.book[*].title → get all titles
echo '{"store":{"book":[{"title":"Moby Dick"},{"title":"Gatsby"}]}}' | \
jq '.store.book[].title'
# → "Moby Dick"
# → "Gatsby"
# $..price → recursive descent for "price" keys
echo '{"a":{"price":1},"b":{"price":2}}' | \
jq '.. | .price? // empty'
# → 1
# → 2
# Filter: books where price < 10
echo '{"store":{"book":[{"title":"A","price":8},{"title":"B","price":12}]}}' | \
jq '.store.book[] | select(.price < 10)'
# → {"title":"A","price":8}