JSON é, atu­al­mente, um dos formatos mais im­por­tan­tes para a troca de dados entre apli­ca­ções, es­pe­ci­al­mente on-line. JSONPath é uma linguagem de expressão que pode ser usada para ler dados es­pe­cí­fi­cos de objetos JSON. Neste artigo, acompanhe a im­ple­men­ta­ção do Python JSONPath e aprenda a usá-lo com os nossos exemplos sim­pli­fi­ca­dos e fáceis de entender.

O que é Python JSONPath?

JSON é um formato de arquivo mul­ti­pla­ta­forma que pode ser usado para facilitar a troca de dados es­tru­tu­ra­dos entre apli­ca­ções. Arquivos JSON consistem em pares de chave-valor listados. Esses valores podem aceitar di­fe­ren­tes tipos de dados, tanto valores pri­mi­ti­vos quanto objetos. Objetos, por sua vez, podem conter seus próprios pares de chave-valor. Como o JSON é com­pre­en­dido por quase todos os sistemas modernos, ele pode ser usado para trocas de dados entre quaisquer tipos de aplicação, tanto lo­cal­mente quanto pela internet.

Nem toda aplicação, contudo, precisa de todos os dados cap­tu­ra­dos em um arquivo JSON. Para estas, o JSONPath é uma boa escolha. Como pre­vi­a­mente men­ci­o­nado, JSONPath é uma linguagem de expressão que pode ser usada para ler in­for­ma­ções es­pe­cí­fi­cas de objetos JSON. Na maioria das lin­gua­gens de pro­gra­ma­ção, o JSONPath precisa ser importado de uma bi­bli­o­teca externa. Como essas bi­bli­o­te­cas precisam ser im­ple­men­ta­das se­pa­ra­da­mente para cada linguagem, elas e o processo de im­ple­men­ta­ção podem diferir li­gei­ra­mente.

Módulo Python JSONPath

A im­ple­men­ta­ção Python mais comum do JSONPath é, pro­va­vel­mente, jsonpath-ng, apesar de haver outras opções de im­ple­men­ta­ção de JSONPath para Python, como jsonpath e jsonpath-rw. No entanto, essas opções são menos populares e oferecem fun­ci­o­na­li­da­des mais limitadas, o que torna o jsonpath-ng a escolha mais re­co­men­dada..

Ins­ta­la­ção

Você pode instalar o jsonpath-ng de forma muito simples pelo terminal. Basta inserir o comando pip install jsonpath-ng para começar.

Dica

Essa ins­ta­la­ção é feita por meio do ge­ren­ci­a­dor de pacotes pip, que é usado por padrão no Python. Caso você não tenha este ge­ren­ci­a­dor de pacotes instalado, será ne­ces­sá­rio baixá-lo primeiro. Mais in­for­ma­ções podem ser en­con­tra­das no site do Pip.

Sintaxe

O JSONPath pode ser usado para executar consultas complexas em objetos JSON. No módulo, existem di­fe­ren­tes métodos, ope­ra­do­res e ex­pres­sões atômicas que podem ser usados para se­le­ci­o­nar e consultar dados es­pe­cí­fi­cos. Os dois métodos JSONPath mais im­por­tan­tes são parse() e find(). Com parse(), você define consultas, que podem ser re­fe­ren­ci­a­das e repetidas quantas vezes for ne­ces­sá­rio. Com find(), você executa essas consultas em dados JSON para extrair valores concretos. O exemplo a seguir explica melhor:

import json
import jsonpath_ng as jp
raw_data = '''
{
    "name": "John",
    "age": 30,
    "place of residence": "New York"
}
'''
json_object = json.loads(raw_data)
name_query = jp.parse("$.name")
result = name_query.find(json_object)
print(result[0].value) # saída: John
Python

No exemplo acima, dados JSON no formato de string foram con­ver­ti­dos em um di­ci­o­ná­rio, graças ao json.loads - este é o formato com o qual o Python funciona melhor. Ao criar o name_query, a consulta $.name foi definida, par retornar o valor de name. Isso foi então aplicado ao objeto JSON, com find(). O resultado da consulta foi ar­ma­ze­nado na variável result e lido com result[0].value.

Dica

Para que o Python possa ler dados JSON de uma string ou de um arquivo JSON, o módulo Python json deve ser incluído, como fizemos no exemplo acima. Strings e arquivos podem então ser con­ver­ti­dos em um formato legível pelo Python, por loads() ou load().

O método find não retorna apenas o valor so­li­ci­tado, mas também outras in­for­ma­ções con­tex­tu­ais, como o caminho para o valor procurado. Essa in­for­ma­ção é retornada na forma de uma lista, na qual o valor procurado recebe o índice 0. Então, você poderá usar result[0].value para exibir o valor desejado.

No exemplo acima, o cifrão foi usado para definir a consulta. Este é um operador atômico que se refere ao objeto raiz do JSON. Todos os ope­ra­do­res e ex­pres­sões atômicas estão listados na tabela a seguir.

Expressão/Operador Sig­ni­fi­cado Exemplo Ex­pli­ca­Ã§Ã£o
$ Objeto raiz $.marcus.age Procura o valor da chave “age” do objeto “marcus”.
. Campo de um objeto $.marcus Procura “marcus”, onde “marcus” é um campo do objeto raiz.
.. Pesquisa recursiva por um campo. Campos em su­bob­je­tos também são pes­qui­sa­dos. $.people..age Retorna todas as ocor­rên­cias do campo “age” em pessoas e seus su­bob­je­tos.
[x] Elemento em um array $.people[5] Procura o sexto elemento (no índice 5) no array “people”.
\* Curinga, ge­ral­mente usado em conexão com loops ‘$.people[*]’ Procura um campo em “people”. Combinado com um loop, cada campo é retornado por vez.

Na im­ple­men­ta­ção em Python do JSONPath, filtros podem ser usados para tornar sua pesquisa ainda mais es­pe­cí­fica. Essas consultas podem ser feitas com a ajuda de ope­ra­do­res Python. A tabela abaixo mostra todos os símbolos com exemplos:

Símbolos Sig­ni­fi­cado Exemplo Ex­pli­ca­Ã§Ã£o
.[?(filtro)] Sintaxe geral para filtros. Pa­rên­te­ses podem ser omitidos. $.people[?(@.name == "Anne")] Procura pessoas cujo nome seja “Anne”.
@ Objeto atu­al­mente sendo pes­qui­sado, muitas vezes usado em conexão com loops. $.people[?(@.age < 50)] Procura campos em “people” cujo valor para “age” seja menor que 50.
<, >, <=, >=, == e!= Ope­ra­do­res de com­pa­ra­Ã§Ã£o que podem ser usados para filtrar re­sul­ta­dos es­pe­cí­fi­cos. $.people[@.age < 50 & @.age > 20] Procura pessoas com idade entre 20 e 50 anos.
Dica

Se você deseja usar filtros, terá de incluir o módulo jsonpath_ng.ext e re­fe­ren­ciá-lo ade­qua­da­mente, ao chamar parse().

Exemplo de aplicação de Python JSONPath

import json
import jsonpath_ng as jp
# Dados JSON como string
data = """
{
    "cities": [
        {
            "name": "Trenton",
            "state": "New Jersey",
            "residents": 90048,
            "iscapital": true,
            "neighborhood Central West": {
                "residents": 1394    
            }
        },
        {
            "name": "Hamburg",
            "state": "Hamburg",
            "residents": 1841000,
            "iscapital": false
        },
        {
            "name": "New York City",
            "state": "New York",
            "residents": 8804190,
            "iscapital": false
        },
        {
            "name": "Los Angeles",
            "state": "California",
            "residents": 3898767
        }
    ]
}
"""
# Converter dados de string para dicionário
json_data = json.loads(data)
# Consulta: Nomes de todas as cidades
query1 = jp.parse("cities[*].name")
for match in query1.find(json_data):
    print(match.value)  # saída: Trenton, Hamburg, New York City, Los Angeles
# Importar jsonpath_ng.ext para aplicar filtros
import jsonpath_ng.ext as jpx
# Consulta: Nomes de todas as cidades com menos de 1,5 milhão de habitantes
query2 = jpx.parse("$.cities[?(@.residents < 1500000)].name")
for match in query2.find(json_data):
    print(match.value)  # saída: Trenton
# Todos os campos rotulados como “residents”
query3 = jp.parse("$.cities..residents")
match = query3.find(json_data)
for i in match:
    print(i.value)  # saída: 1394, 1841000, 8804190, 3898767
# Os nomes de todas as cidades que não se chamam “Trenton”
query4 = jpx.parse('$.cities[?(@.name != "Trenton")].name')
for match in query4.find(json_data):
    print(match.value)  # saída: Hamburg, New York City, Los Angeles
Python

No exemplo acima, os dados JSON são es­pe­ci­fi­ca­dos como uma string e depois con­ver­ti­dos em um objeto di­ci­o­ná­rio, por loads(). Há apenas um único array no objeto raiz, que, por sua vez, contém 4 cidades. Cada cidade possui 4 campos com os seguintes dados:

  • Nome da cidade
  • Estado da cidade
  • Número de ha­bi­tan­tes
  • Se a cidade é a capital ou não

New Jersey possui um campo adicional, chamado “Central West”, que também possui um número de ha­bi­tan­tes.

Após os dados serem con­ver­ti­dos para um formato adequado, 4 consultas di­fe­ren­tes são exe­cu­ta­das. Suas funções e saídas estão indicadas como co­men­tá­rios no exemplo. Você pode notar que cinco valores foram re­tor­na­dos na terceira consulta. Isso ocorre porque o operador “..” pesquisa re­cur­si­va­mente por campos cor­res­pon­den­tes. Isso significa que todos os objetos são pes­qui­sa­dos, bem como todos os filhos desses objetos. Assim, o número de ha­bi­tan­tes de Central West é listado ao lado do número de ha­bi­tan­tes das cidades.

Dica

Em com­bi­na­ção, JSON e Python formam uma fer­ra­menta versátil para programar na internet. Se você tem uma aplicação web que deseja publicar com rapidez, fa­ci­li­dade e di­re­ta­mente do Git, o Deploy Now da IONOS é a solução ideal.

Ir para o menu principal