Formatos e fontes de dados 7 min de leitura

Parsing de JSON

Parsing de JSON em detalhe: estruturas aninhadas, streaming de arquivos grandes, JSONPath e os erros típicos ao trabalhar com APIs.

EW
Equipe Web-Scraping.biz
Coleta de dados para as demandas do negócio
Publicado: 16 março 2025

O que é JSON

JSON (JavaScript Object Notation) é um formato de texto para o intercâmbio de dados, prático tanto para a leitura por pessoas quanto para o processamento por máquinas. Apesar de ter nascido no JavaScript, há muito se tornou um padrão independente de linguagem e é usado praticamente em qualquer lugar onde aplicações precisam trocar dados estruturados.

Exemplo básico de um documento JSON:

json
{
  "id": 42,
  "name": "Ana",
  "is_active": true,
  "roles": ["admin", "editor"],
  "profile": {
    "city": "São Paulo",
    "age": 29
  }
}

O formato se compõe de poucos tipos simples: objetos (pares «chave-valor»), arrays, strings, números, valores booleanos e null. Essa simplicidade é justamente a causa da sua difusão universal.

O que é o parsing de JSON e para que serve

O parsing de JSON (análise sintática) é o processo de converter o texto JSON em uma estrutura de dados que uma linguagem de programação específica entenda: um objeto, um dicionário, um array, uma lista etc. Em essência, o parser recebe uma cadeia de caracteres e a transforma em objetos vivos com os quais se pode trabalhar no código.

O processo inverso — converter os objetos do programa de volta em uma string JSON — chama-se serialização (ou marshalling). Parsing e serialização quase sempre andam em par.

O parsing aparece em tarefas muito comuns:

  • Trabalho com APIs — recepção e envio de dados por HTTP (detalhamos mais abaixo).
  • Arquivos de configuração — muitas ferramentas guardam seus ajustes em JSON (package.json, tsconfig.json etc.).
  • Armazenamento e intercâmbio de dados — logs, mensagens em filas (Kafka, RabbitMQ), documentos em bancos NoSQL (MongoDB).
  • Comunicação entre serviços em uma arquitetura de microsserviços.
  • Persistência do estado da aplicação em arquivos ou no localStorage do navegador.

Parsing de JSON no trabalho com APIs

O cenário mais frequente em que quem desenvolve se depara com o parsing de JSON é a interação com uma API. A imensa maioria das APIs web modernas (REST e, com frequência, outros estilos) troca dados justamente em formato JSON.

O ciclo típico de trabalho com uma API é o seguinte:

  1. O cliente envia uma requisição HTTP a um endpoint da API.
  2. O servidor responde com um corpo em forma de string JSON.
  3. O cliente parseia essa string, converte-a em objetos e segue trabalhando com os dados.
  4. Ao enviar dados (POST, PUT), o cliente faz o contrário: serializa seus objetos para JSON.

Sem a etapa de parsing, a resposta do servidor não passa de texto, com o qual não dá para trabalhar confortavelmente de forma programática. Por isso o parsing é um elo obrigatório em quase qualquer integração com um serviço externo.

Veja também: o artigo «Extração de dados via API» — lá explicamos em detalhe como se estruturam as requisições a uma API, como processar as respostas e trabalhar com cabeçalhos, códigos de status, paginação e autenticação. Este artigo se concentra justamente na etapa de análise dos próprios dados JSON, que faz parte desse processo.

Exemplos de parsing de JSON em diferentes linguagens

A seguir, exemplos de parsing de JSON em linguagens populares. Em todos os casos, parseia-se a mesma string e depois extrai-se o valor de um campo aninhado.

Python

A biblioteca padrão inclui o módulo json. O método loads parseia uma string; load, o conteúdo de um arquivo.

python
import json

data_str = '{"name": "Ana", "profile": {"city": "São Paulo", "age": 29}}'

# Parsing da string para um dicionário
data = json.loads(data_str)

print(data["name"])              # Ana
print(data["profile"]["city"])   # São Paulo

# Operação inversa: serialização
back_to_str = json.dumps(data, ensure_ascii=False)

JavaScript

No JavaScript, o parsing está integrado à linguagem por meio do objeto global JSON. É, de fato, o formato «nativo» do ecossistema.

javascript
const dataStr = '{"name": "Ana", "profile": {"city": "São Paulo", "age": 29}}';

// Parsing da string para um objeto
const data = JSON.parse(dataStr);

console.log(data.name);            // Ana
console.log(data.profile.city);    // São Paulo

// Operação inversa
const backToStr = JSON.stringify(data);

Ao trabalhar com fetch, o parsing da resposta da API se faz em uma única linha:

javascript
const response = await fetch("https://api.example.com/users/42");
const user = await response.json(); // a resposta já chega parseada como objeto
console.log(user.name);

Java

A biblioteca padrão não traz um parser integrado, então costuma-se usar bibliotecas — por exemplo, Jackson ou Gson. Exemplo com Jackson:

java
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) throws Exception {
        String dataStr = "{\"name\": \"Ana\", \"profile\": {\"city\": \"São Paulo\"}}";

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(dataStr);

        System.out.println(node.get("name").asText());                  // Ana
        System.out.println(node.get("profile").get("city").asText());   // São Paulo
    }
}

O mais comum é parsear o JSON diretamente para uma classe tipada (POJO):

java
record Profile(String city, int age) {}
record User(String name, Profile profile) {}

User user = mapper.readValue(dataStr, User.class);
System.out.println(user.profile().city());

Go

A biblioteca padrão inclui o pacote encoding/json. Os dados costumam ser parseados para uma struct com tags nos campos.

go
package main

import (
    "encoding/json"
    "fmt"
)

type Profile struct {
    City string `json:"city"`
    Age  int    `json:"age"`
}

type User struct {
    Name    string  `json:"name"`
    Profile Profile `json:"profile"`
}

func main() {
    dataStr := `{"name": "Ana", "profile": {"city": "São Paulo", "age": 29}}`

    var user User
    json.Unmarshal([]byte(dataStr), &user)

    fmt.Println(user.Name)          // Ana
    fmt.Println(user.Profile.City)  // São Paulo
}

C

O .NET moderno inclui o namespace integrado System.Text.Json.

c#
using System;
using System.Text.Json;

class Program
{
    static void Main()
    {
        string dataStr = "{\"name\": \"Ana\", \"profile\": {\"city\": \"São Paulo\"}}";

        using JsonDocument doc = JsonDocument.Parse(dataStr);
        JsonElement root = doc.RootElement;

        Console.WriteLine(root.GetProperty("name").GetString());                       // Ana
        Console.WriteLine(root.GetProperty("profile").GetProperty("city").GetString()); // São Paulo
    }
}

PHP

No PHP, o parsing está integrado à linguagem pelas funções json_decode e json_encode.

php
<?php
$dataStr = '{"name": "Ana", "profile": {"city": "São Paulo", "age": 29}}';

// true: parseia para um array associativo em vez de um objeto
$data = json_decode($dataStr, true);

echo $data["name"];             // Ana
echo $data["profile"]["city"];  // São Paulo

// Operação inversa
$backToStr = json_encode($data, JSON_UNESCAPED_UNICODE);

Rust

No ecossistema Rust, o padrão de facto é o crate serde junto com serde_json.

rust
use serde::Deserialize;

#[derive(Deserialize)]
struct Profile {
    city: String,
    age: u32,
}

#[derive(Deserialize)]
struct User {
    name: String,
    profile: Profile,
}

fn main() {
    let data_str = r#"{"name": "Ana", "profile": {"city": "São Paulo", "age": 29}}"#;

    let user: User = serde_json::from_str(data_str).unwrap();

    println!("{}", user.name);          // Ana
    println!("{}", user.profile.city);  // São Paulo
}

Comparação de abordagens

Linguagem Ferramenta Integrada à linguagem
Python json Sim
JavaScript JSON Sim
Java Jackson / Gson Não
Go encoding/json Sim
C# System.Text.Json Sim
PHP json_decode Sim
Rust serde / serde_json Não

Percebem-se duas abordagens principais para a análise:

  • Parsing dinâmico — o JSON vira uma estrutura genérica (dicionário, array, árvore de nós). Prático para um trabalho rápido e flexível, mas sem verificação de tipos em tempo de compilação.
  • Parsing tipado — o JSON é mapeado diretamente para classes ou structs definidas de antemão. Mais seguro e mais claro, sobretudo em linguagens de tipagem estrita (Java, Go, Rust, C#).

Problemas frequentes e recomendações

Ao parsear JSON, convém levar em conta várias dificuldades típicas:

  • JSON inválido. Se a string estiver corrompida ou contiver erros de sintaxe, o parser lançará uma exceção. Envolva sempre a análise de dados externos em tratamento de erros.
  • Campos ausentes ou null. Não presuma que todas as chaves esperadas estão sempre presentes: a API pode enviar um objeto incompleto. Verifique se o campo existe antes de acessá-lo.
  • Codificação. O padrão JSON usa UTF-8. Em algumas linguagens (Python, PHP), é preciso indicar flags de forma explícita para que os caracteres não ASCII (acentos, cedilha) não virem sequências \u ao serializar.
  • Documentos grandes. Para arquivos muito grandes, em vez de carregar o objeto inteiro na memória, recorre-se ao parsing em fluxo (streaming), que lê os dados por partes.
  • Números e precisão. Inteiros grandes e números de ponto flutuante podem perder precisão — algo crítico para dados financeiros, que às vezes são transmitidos como strings.

Conclusão

O parsing de JSON é uma habilidade básica sem a qual é quase impossível trabalhar com as APIs modernas e trocar dados entre sistemas. O formato em si é universal, e as ferramentas para analisá-lo existem em todas as linguagens de programação difundidas: umas integradas, outras em forma de bibliotecas populares. O princípio é sempre o mesmo — converter uma cadeia de texto em objetos práticos para o código e, quando necessário, percorrer o caminho inverso.

Para ver como o parsing se encaixa no ciclo completo de interação com serviços externos, consulte o artigo «Extração de dados via API».