Módulo 7 - Trabalhando com JSON

Dados aninhados: listas dentro de dicionários

11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Entender como o JSON aninha listas dentro de dicionários e vice-versa.
  • Acessar campos em vários níveis de profundidade com colchetes.
  • Percorrer estruturas aninhadas combinando laços e acesso por chave.
  • Ler uma resposta de API típica e extrair a informação desejada.

Como o JSON se aninha

Os exemplos das aulas anteriores foram rasos de propósito. Na vida real, o JSON de uma API ou de um arquivo de configuração tem várias camadas. Um pedido tem uma lista de itens; cada item tem nome, preço e quantidade; o pedido inteiro pertence a um cliente, que por sua vez tem endereço. Tudo isso vira dicionários e listas encaixados. A habilidade a treinar aqui é navegar por essas camadas sem se perder. Veja um exemplo com dois níveis.

import json

texto = """
{
  "cliente": "Marina",
  "cidade": "Curitiba",
  "pedidos": [
    {"produto": "Livro", "valor": 59.9},
    {"produto": "Caneta", "valor": 4.5}
  ]
}
"""

dados = json.loads(texto)

print(dados["cliente"])              # Marina
print(dados["pedidos"][0]["produto"]) # Livro
print(dados["pedidos"][1]["valor"])   # 4.5

Encadear colchetes desce nas camadas: primeiro a lista pedidos, depois o item, depois o campo.

Leia o acesso dados["pedidos"][0]["produto"] da esquerda para a direita, um passo por vez. Primeiro dados["pedidos"] pega a lista de pedidos. Depois [0] pega o primeiro item dessa lista, que é um dicionário. Por fim ["produto"] pega o campo produto desse dicionário. Cada colchete desce uma camada. Se ler assim, devagar, nenhuma estrutura aninhada assusta, por mais fundo que ela vá.

Percorrendo camadas com laços

Acessar um item pelo índice serve quando você sabe a posição. Mas quase sempre você quer percorrer todos os itens de uma lista aninhada. Aí entram os laços, às vezes um dentro do outro. Para somar o valor de todos os pedidos, você percorre a lista pedidos e, a cada volta, acessa o campo valor. Quando há listas dentro de listas, o laço aninhado percorre cada camada. Veja como calcular o total de um pedido.

import json

texto = """
{
  "cliente": "Marina",
  "pedidos": [
    {"produto": "Livro", "valor": 59.9},
    {"produto": "Caneta", "valor": 4.5},
    {"produto": "Caderno", "valor": 22.0}
  ]
}
"""

dados = json.loads(texto)

total = 0
for pedido in dados["pedidos"]:
    print(pedido["produto"], "custa", pedido["valor"])
    total = total + pedido["valor"]

print("Total:", round(total, 2))
# Livro custa 59.9
# Caneta custa 4.5
# Caderno custa 22.0
# Total: 86.4

Um laço percorre a lista de pedidos, imprime cada um e acumula o total.

Uma tática que salva muito tempo é explorar antes de programar. Ao receber um JSON desconhecido, converta com loads e dê um print no resultado, ou imprima as chaves de cada nível. Assim você enxerga a estrutura real em vez de adivinhar. Muitos erros com JSON aninhado vêm de supor uma forma que não é a verdadeira, por exemplo achar que um campo é dicionário quando é lista. Explorar primeiro elimina esse tipo de tropeço.

Lendo uma resposta de API típica

Respostas de API seguem muito esse padrão aninhado, e costumam ter campos que nem sempre aparecem. Por isso o método .get() é útil: ele devolve None quando a chave não existe, em vez de quebrar. Imagine uma resposta com uma lista de usuários, cada um com um endereço opcional. O código a seguir percorre a lista e usa .get() para lidar com o endereço que pode faltar, sem parar o programa.

import json

resposta = """
{
  "status": "ok",
  "usuarios": [
    {"nome": "Ana", "endereco": {"cidade": "Recife"}},
    {"nome": "Léo"}
  ]
}
"""

dados = json.loads(resposta)

for usuario in dados["usuarios"]:
    endereco = usuario.get("endereco")
    if endereco:
        print(usuario["nome"], "mora em", endereco["cidade"])
    else:
        print(usuario["nome"], "sem endereço informado")
# Ana mora em Recife
# Léo sem endereço informado

O .get() evita erro quando o campo endereco não existe para todos os usuários.

Repare em dois cuidados que valem para quase toda resposta de API. Primeiro, os dados chegam como texto, então o json.loads é o ponto de partida. Segundo, nem todo campo é garantido, então acessar com .get() e checar antes de descer mais um nível evita o programa quebrar com dados incompletos. Com isso você já consegue consumir a maioria das APIs que vai encontrar, extraindo exatamente a informação que precisa de estruturas grandes.

Teste rápido

Em dados["pedidos"][0]["valor"], o que cada parte faz, na ordem?

Perguntas frequentes

Como sei se um nível do JSON é lista ou dicionário?
Olhe os delimitadores: chaves indicam um objeto, que vira dicionário e é acessado por nome de chave; colchetes indicam um array, que vira lista e é acessado por índice numérico. Na dúvida, imprima o valor com type() para confirmar se é dict ou list antes de acessar.
O que fazer quando um campo pode não existir?
Use o método .get() em vez do acesso com colchetes. O dicionario.get("chave") devolve None quando a chave falta, em vez de levantar KeyError. Você pode até passar um valor padrão, como dicionario.get("cidade", "não informada"), para ter algo útil no lugar do None.
Tem limite de níveis de aninhamento?
Na prática, não para o que você vai encontrar; o JSON pode aninhar muitas camadas. O que muda é a clareza do código. Quando o acesso fica com muitos colchetes seguidos, vale guardar níveis intermediários em variáveis com nomes claros para não se perder e facilitar a leitura.
Preciso de laços aninhados sempre que o JSON aninha?
Só quando você precisa percorrer listas dentro de listas. Se um nível é acessado por uma chave fixa, um acesso direto basta. O laço aninhado entra quando há uma lista cujos itens contêm outra lista que também precisa ser percorrida item a item.
Como exploro um JSON grande que não conheço?
Converta com json.loads e imprima aos poucos: comece por dados.keys() para ver as chaves do topo, depois desça em cada nível conferindo o tipo e as chaves. Você também pode imprimir com json.dumps e indent=2 para ver a estrutura formatada e entender o formato antes de escrever o código.
Posso modificar um JSON aninhado depois de carregar?
Sim. Como o resultado é feito de dicionários e listas comuns, você altera valores em qualquer nível, adiciona itens a listas internas e remove chaves. Depois de mudar, é só gravar de volta com json.dump se quiser persistir as alterações no arquivo.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.