JSONPath Tutorial: Query JSON Like a Pro
Master JSONPath syntax with practical examples. Learn every operator, filter expression, and real-world query pattern to extract data from complex JSON structures.
O que é JSONPath?
JSONPath é uma linguagem de consulta para JSON, semelhante ao que o XPath faz para XML. Ela permite entrar em uma estrutura JSON complexa e extrair exatamente os dados de que você precisa usando uma sintaxe de expressão concisa. Em vez de escrever laços e condicionais para percorrer objetos e arrays aninhados, você escreve uma única expressão de caminho como $.store.book[?(@.price < 10)].title e obtém todos os títulos de livros com preço abaixo de dez dólares.
Stefan Goessner apresentou o JSONPath em 2007, e desde então ele se tornou um padrão de fato em várias linguagens e ferramentas. Se você trabalha com APIs REST, arquivos de configuração ou qualquer dado JSON não trivial, o JSONPath vai economizar bastante tempo.
JSONPath vs. XPath: comparação rápida
Se você já conhece XPath, o JSONPath vai parecer familiar. A diferença principal é que o JSON tem um modelo de dados mais simples — objetos e arrays em vez de elementos, atributos e namespaces. Veja como os dois se comparam:
| Conceito | XPath | JSONPath |
|---|---|---|
| Raiz | / | $ |
| Filho | /child | .child ou ['child'] |
| Descida recursiva | // | .. |
| Curinga | * | * |
| Índice de array | [1] (base 1) | [0] (base 0) |
| Filtro | [predicate] | [?(expression)] |
Referência completa de operadores JSONPath
Toda expressão JSONPath parte da raiz $ e encadeia operadores para navegar mais fundo. Aqui estão todos os operadores que você precisa conhecer:
| Operador | Descrição | Exemplo |
|---|---|---|
$ | O objeto ou array raiz | $ — o documento inteiro |
.key | Membro filho pelo nome (notação com ponto) | $.store.name |
['key'] | Membro filho pelo nome (notação com colchetes) | $['store']['name'] |
.. | Descida recursiva — busca em todos os descendentes | $..price — todo campo "price" |
* | Curinga — todos os membros de um objeto ou array | $.store.* |
[n] | Índice de array (base 0) | $.items[0] |
[start:end] | Fatia de array (o fim é exclusivo) | $.items[0:3] — os três primeiros itens |
[start:end:step] | Fatia de array com passo | $.items[::2] — um sim, um não |
[n,m] | Vários índices de array | $.items[0,2,4] |
[?()] | Expressão de filtro | $.items[?(@.price > 10)] |
@ | Nó atual (usado dentro de filtros) | @.name == 'Alice' |
JSON de exemplo para nossos exemplos
Usaremos este documento JSON ao longo do tutorial. Ele representa uma resposta pequena de API de uma livraria:
{
"store": {
"name": "TechBooks Online",
"book": [
{ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95, "inStock": true },
{ "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, "inStock": false },
{ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99, "inStock": true },
{ "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99, "inStock": true }
],
"bicycle": { "color": "red", "price": 19.95 }
}
}
Exemplos práticos de JSONPath
1. Obter o nome da loja
$.store.name
Resultado: "TechBooks Online"
2. Obter todos os títulos dos livros
$.store.book[*].title
Resultado: ["Sayings of the Century","Sword of Honour","Moby Dick","The Lord of the Rings"]
3. Obter o primeiro livro
$.store.book[0]
Resultado: o objeto inteiro do primeiro livro.
4. Obter o último livro
$.store.book[-1]
Índices negativos contam a partir do fim. -1 retorna o último elemento.
5. Fatia: os dois primeiros livros
$.store.book[0:2]
Retorna os livros nos índices 0 e 1. O índice final é exclusivo.
6. Obter todos os preços em todo o documento
$..price
Resultado: [8.95, 12.99, 8.99, 22.99, 19.95]
O operador de descida recursiva .. encontra todo campo price, independentemente da profundidade.
7. Filtro: livros abaixo de US$ 10
$.store.book[?(@.price < 10)]
Retorna os dois livros com preço 8,95 e 8,99.
8. Filtro: livros que têm ISBN
$.store.book[?(@.isbn)]
Retorna apenas Moby Dick e The Lord of the Rings.
9. Filtro: livros de ficção em estoque
$.store.book[?(@.category == 'fiction' && @.inStock == true)]
Combine condições com && (e) e || (ou).
10. Vários índices
$.store.book[0,3]
Escolha elementos específicos.
11. Curinga em objeto
$.store.bicycle.*
Resultado: ["red", 19.95]
12. Obter autores de livros caros
$.store.book[?(@.price > 15)].author
Resultado: ["J. R. R. Tolkien"]
Experimente você mesmo: cole o JSON de exemplo acima e teste essas expressões no nosso JSONPath Tester.
Expressões de filtro em profundidade
As expressões de filtro são a parte mais poderosa do JSONPath. Elas ficam dentro de [?()] e avaliam uma condição booleana para cada elemento.
| Operador | Significado | Exemplo |
|---|---|---|
== | Igual a | @.status == 'active' |
!= | Diferente de | @.role != 'admin' |
> | Maior que | @.age > 18 |
>= | Maior ou igual | @.score >= 90 |
< | Menor que | @.price < 50 |
<= | Menor ou igual | @.quantity <= 0 |
=~ | Correspondência por regex (em algumas implementações) | @.name =~ /^J.*/ |
&& | E lógico | @.price > 5 && @.price < 20 |
| ` | ` |
Um padrão comum é verificar se a propriedade existe. Escrever @.isbn sem operador de comparação retorna true se a propriedade existir e não for null.
Cenários do mundo real
Extrair todos os e-mails de uma resposta de API
$..email
O operador de descida recursiva encontra todo campo email, não importa onde esteja na hierarquia.
Encontrar produtos por faixa de preço
$.products[?(@.price >= 25 && @.price <= 100)]
Obter valores de configuração aninhados
$.config.database.connections[0].host
JSONPath em diferentes linguagens
JavaScript / Node.js
import { JSONPath } from "jsonpath-plus";
const data = { store: { book: [{ title: "Moby Dick", price: 8.99 }] } };
const titles = JSONPath({ path: "$.store.book[*].title", json: data });
console.log(titles); // ["Moby Dick"]
Python
from jsonpath_ng.ext import parse
data = {"store": {"book": [{"title": "Moby Dick", "price": 8.99}]}}
expr = parse("$.store.book[*].title")
matches = [match.value for match in expr.find(data)]
print(matches) # ['Moby Dick']
Java
import com.jayway.jsonpath.JsonPath;
String json = "{\"store\":{\"book\":[{\"title\":\"Moby Dick\",\"price\":8.99}]}}";
List<String> titles = JsonPath.read(json, "$.store.book[*].title");
System.out.println(titles); // [Moby Dick]
Armadilhas e limitações
- Sem especificação formal (até pouco tempo atrás). O IETF publicou o RFC 9535 em 2024 para padronizar a sintaxe, mas muitas bibliotecas ainda seguem a especificação original de Goessner.
- Suporte a regex varia. O operador
=~não é suportado em todos os lugares. - Sem operações de escrita. JSONPath é somente leitura.
- Desempenho em documentos enormes. A descida recursiva (
..) percorre todos os nós. - Inconsistência no tipo de retorno. Algumas bibliotecas retornam um único valor; outras sempre retornam um array.
- Caracteres especiais nas chaves. Use notação com colchetes para chaves com pontos ou espaços.
JSONPath vs. jq
- JSONPath foi pensado para embutir em código de aplicação, com suporte de bibliotecas nas principais linguagens.
- jq é uma linguagem completa de transformação de dados, mais poderosa, porém com curva de aprendizado mais íngreme.
Para consultar dados dentro de uma aplicação, JSONPath é a escolha pragmática. Para scripts de shell e pipelines de dados, o jq é difícil de superar.
Folha de referência rápida
| O que você quer | JSONPath |
|---|---|
| Documento inteiro | $ |
| Propriedade específica | $.user.name |
| Todos os itens do array | $.items[*] |
| Primeiro item | $.items[0] |
| Último item | $.items[-1] |
| Intervalo de itens | $.items[1:4] |
| Cada enésimo item | $.items[::2] |
| Todos os campos "name" em qualquer lugar | $..name |
| Filtrar por valor | $.items[?(@.price < 10)] |
| Filtrar por existência | $.items[?(@.discount)] |
| Várias condições | $.items[?(@.qty > 0 && @.active)] |
Experimente você mesmo: abra o JSONPath Tester para executar consultas nos seus próprios dados JSON em tempo real.