Artigo original: Python Read JSON File – How to Load JSON from a File and Parse Dumps

Boas vindas! Se quiserem aprender a trabalhar com arquivos JSON em Python, este artigo é para vocês.

Nele, vocês aprenderão:

  • O motivo de o formato JSON ser tão importante.
  • Sua estrutura básica e tipos de dados.
  • Como o JSON e dicionários em Python funcionam juntos na linguagem.
  • Como trabalhar com o módulo json integrado do Python.
  • Como converter strings do JSON em objetos do Python e vice-versa.
  • Como usar loads() e dumps()
  • Como indentar as strings do JSON automaticamente.
  • Como ler os arquivos JSON em Python usando load()
  • Como gravar em arquivos JSON no Python usando dump()
  • E mais!

Estão prontos? Vamos começar! ✨

🔹 Introdução: O que é JSON?

image-98

O formato JSON foi inspirado originalmente na sintaxe do JavaScript (uma linguagem de programação usada em desenvolvimento para a web). Porém, desde então, ele se tornou um formato de dados independente de linguagem e a maioria das linguagens de programação que utilizamos hoje pode gerar e ler JSON.

Importância e casos de uso do JSON

O JSON é, basicamente, um formato usado para armazenam ou representar dados. É comum que os casos de uso incluam o desenvolvimento para a web e arquivos de configuração.

Vejamos o motivo:

  • Desenvolvimento para a web: o JSON normalmente é usado para enviar dados do servidor para o client e vice-versa em aplicações para a web.
image-65
  • Arquivos de configuração: o JSON também é usado para armazenar configurações e definições. Por exemplo, para criar um app do Google Chrome, você precisa incluir um arquivo no formato JSON chamado manifest.json para especificar o nome do app, sua descrição, versão atual e outras propriedades e definições.
image-99

🔸 Estrutura e formato do JSON

Agora que você sabe para que o formato JSON é usado, vejamos sua estrutura básica com um exemplo que representa os dados de um pedido de pizza:

{ 
	"size": "medium",
	"price": 15.67,
	"toppings": ["mushrooms", "pepperoni", "basil"],
	"extra_cheese": false,
	"delivery": true,
	"client": {
		"name": "Jane Doe",
		"phone": null,
		"email": "janedoe@email.com"
	}
}
Exemplo de arquivo .json

Essas são as características principais do formato JSON:

  • Há uma sequência de pares chave-valor envolvidos por chaves {}.
  • Cada chave é mapeada para um valor específico usando este formato:
"chave": <valor> 

💡 Dica: Os valores que exigem aspas precisam ser envolvidos por aspas duplas.

  • Pares chave-valor são separados por uma vírgula. Somente o último par não é seguido por uma vírgula.
{
	"size": "medium", # Vírgula!
	"price": 15.67
}

💡 Dica: Tipicamente, formatamos o JSON com níveis diferentes de indentação para tornar os dados mais fáceis de ler. Neste artigo, aprenderemos como adicionar a indentação automaticamente com o Python.

Tipos de dados do JSON: chaves e valores

Os arquivos JSON têm regras específicas que determinam que tipos de dados são válidos como chaves e valores.

  • Chaves devem ser strings.
  • Valores podem ser strings, números, um array, um valor booleano (true/ false), null ou um objeto JSON.

De acordo com a documentação do Python:

Chaves nos pares chave/valor de JSON são sempre do tipo str. Quando um dicionário é convertido para JSON, todas as chaves são convertidas para strings.

Guia de estilo

De acordo com o Guia de estilo de JSON do Google (em inglês):

  • Sempre escolha nomes significativos.
  • Tipos de array devem ter nomes de chave no plural. Todos os outros nomes de chave devem estar no singular. Por exemplo: use "orders" em vez de "order" se o valor correspondente for um array.
  • Não deve haver comentários em objetos JSON.

🔹 JSON x dicionários em Python

Arquivos JSON e dicionários podem parecer muito semelhantes para começar (visualmente), mas eles são bem diferentes. Vamos ver como eles estão "conectados" e como eles se complementam para tornar o Python uma ferramenta poderosa de trabalho com arquivos JSON.

JSON é um formato de arquivo usado para representar e armazenar dados, enquanto um dicionário em Python é a estrutura de dados de fato (o objeto) que é mantida na memória enquanto um programa em Python é executado.

Como funcionam juntos o JSON e os dicionários em Python

image-100

Quando trabalhamos com arquivos JSON em Python, não podemos simplesmente ler e usar os dados em nosso programa diretamente. Isso ocorre porque o arquivo inteiro seria representado como uma única string e não conseguiríamos acessar os valores de chave-valor de modo individual.

A não ser que...

usássemos os pares chave-valor do arquivo JSON para criar um dicionário em Python que pudéssemos usar em nosso programa para ler os dados, usá-los e modificá-los (se necessário).

Essa é a conexão principal entre o JSON e os dicionários em Python. O JSON é a representação em formato string dos dados e os dicionários são as estruturas de dados que estão de fato na memória e que são criadas quando o programa é executado.

Ótimo. Agora que sabemos mais sobre o JSON, vamos nos aprofundar nos aspectos práticos de como você pode trabalhar com o JSON em Python.

🔸 O módulo JSON

Para nossa sorte, o Python vem com um módulo integrado chamado json. Ele é instalado automaticamente quando você instala o Python e inclui funções para ajudá-lo a trabalhar com arquivos e strings em JSON.

Usaremos esse módulo nos próximos exemplos.

Como importar o módulo JSON

Para usar o json em nosso programa, somente precisamos escrever uma instrução import na parte superior do arquivo.

Assim:

image-73

Com esta linha, você terá acesso às funções definidas no módulo. Usaremos várias delas nos exemplos.

💡 Dica: Se você escrever essa instrução import, precisará usar a sintaxe abaixo para chamar uma função definida no módulo json:

image-76
json.<função>(<args>), onde json é o módulo e args são os argumentos da função

🔹 Python e strings em JSON

Para ilustrar como algumas das mais importantes funções do módulo json funcionam, usaremos uma string de várias linhas com o formato de JSON.

String em JSON

Usaremos essa string específica nos exemplos. É apenas uma string em várias linhas normal em Python que segue o formato de JSON.

data_JSON =  """
{
	"size": "Medium",
	"price": 15.67,
	"toppings": ["Mushrooms", "Extra Cheese", "Pepperoni", "Basil"],
	"client": {
		"name": "Jane Doe",
		"phone": "455-344-234",
		"email": "janedoe@email.com"
	}
}
"""
String em JSON
  • Para definir uma string de várias linhas em Python, usamos aspas triplas.
  • Em seguida, atribuímos a string à variável data_JSON.

💡 Dica: O guia de estilo do Python recomenda usar caracteres de aspas duplas para as aspas triplas ( """ em vez de ''').

Da string em JSON ao dicionário em Python

Usaremos a string com formato JSON para criar um dicionário em Python que possamos acessar, trabalhar com ele e modificá-lo.

Para fazer isso, usaremos a função loads() do módulo json, passando a string como argumento.

Esta é a sintaxe básica:

image-77
json.loads(<JSON_string>), onde json é o módulo, loads é a função e <JSON_string> é a string no formato JSON

Aqui está o código:

# Importar o módulo
import json

# String em formato JSON
data_JSON =  """
{
	"size": "Medium",
	"price": 15.67,
	"toppings": ["Mushrooms", "Extra Cheese", "Pepperoni", "Basil"],
	"client": {
		"name": "Jane Doe",
		"phone": "455-344-234",
		"email": "janedoe@email.com"
	}
}
"""

# Converter a string em JSON em um dicionário
data_dict = json.loads(data_JSON)

Vamos nos concentrar nessa linha:

data_dict = json.loads(data_JSON)
  • json.loads(data_JSON) cria um novo dicionário com os pares chave-valor da string em JSON e retorna esse novo dicionário.
  • Em seguida, o dicionário retornado é atribuído à variável data_dict.

Ótimo! Se imprimirmos o dicionário, veremos esse resultado:

{'size': 'Medium', 'price': 15.67, 'toppings': ['Mushrooms', 'Extra Cheese', 'Pepperoni', 'Basil'], 'client': {'name': 'Jane Doe', 'phone': '455-344-234', 'email': 'janedoe@email.com'}}

O dicionário foi preenchido com os dados da string em JSON. Cada par chave-valor foi adicionado com sucesso.

Agora, vamos ver o que acontece quando tentamos acessar os valores dos pares chave-valor com a mesma sintaxe que usaríamos para acessar um dicionário comum em Python:

print(data_dict["size"])
print(data_dict["price"])
print(data_dict["toppings"])
print(data_dict["client"])

O resultado é:

Medium
15.67
['Mushrooms', 'Extra Cheese', 'Pepperoni', 'Basil']
{'name': 'Jane Doe', 'phone': '455-344-234', 'email': 'janedoe@email.com'}

Exatamente aquilo que esperávamos. Cada chave pode ser usada para acessar seu valor correspondente.

💡 Dica: Podemos usar esse dicionário como qualquer outro dicionário em Python. Por exemplo, podemos chamar métodos de dicionário, adicionar, atualizar, remover pares de chave-valor e muito mais. Também podemos usá-lo em um laço for.

De JSON para Python: conversão de tipo

Quando você usar loads() para criar um dicionário em Python a partir de uma string em JSON, perceberá que alguns valores serão convertidos em seus valores e tipos de dados em Python correspondentes.

Esta tabela apresentada na documentação do Python para o módulo json resume a correspondência dos tipos de dados e valores em JSON para os tipos de dados e valores no Python:

image-79
Tabela apresentada na documentação do módulo JSON oficial

💡 Dica: A mesma tabela de conversão se aplica ao trabalhar com arquivos JSON.

Do dicionário em Python para a string em JSON

Agora você sabe como criar um dicionário em Python a partir de uma string no formato JSON.

Haverá vezes, no entanto, em que poderemos precisar fazer exatamente o contrário, criar uma string em formato JSON a partir de um objeto (por exemplo, um dicionário) para imprimi-lo, exibi-lo, armazená-lo ou trabalhar com ele como uma string.

Para fazer isso, podemos usar a função dumps do módulo json, passando o objeto como argumento:

image-80
json.dumps(<obj>), onde json é o módulo, dumps é a função e obj é o objeto passado como argumento

💡 Dica: Essa função retornará uma string.

Este é um exemplo onde convertemos o dicionário em Python client para uma string como o formato JSON e a armazenamos em uma variável:

# Dicionário em Python
client = {
    "name": "Nora",
    "age": 56,
    "id": "45355",
    "eye_color": "green",
    "wears_glasses": False
}

# Obter uma string formatada em JSON
client_JSON = json.dumps(client)

Vamos nos concentrar nesta linha:

client_JSON = json.dumps(client)
  • json.dumps(client) cria e retorna uma string com todos os pares chave-valor do dicionário no formato JSON.
  • Em seguida, essa string é atribuída à variável client_JSON.

Se imprimirmos essa string, veremos o seguinte resultado:

{"name": "Nora", "age": 56, "id": "45355", "eye_color": "green", "wears_glasses": false}

💡 Dica: Perceba que o último valor (false) foi alterado. No dicionário em Python, este valor era False, mas, em JSON, o valor equivalente é false. Isso nos ajuda a confirmar que, de fato, o dicionário original agora está representado como uma string no formato JSON.

Se verificarmos o tipo de dados dessa variável, veremos que:

<class 'str'>

Assim, o valor retornado por essa função foi, definitivamente, uma string.

De Python para JSON: conversão de tipo

Um processo de conversão de tipo também ocorre quando convertemos um dicionário em uma string em JSON. Esta tabela da documentação do Python ilustra os valores correspondentes:

image-81
Tabela da documentação oficial do módulo JSON.

Como imprimir o JSON com indentação

Se usarmos a função dumps e imprimirmos a string que obtivemos no exemplo anterior, veremos o seguinte:

{"name": "Nora", "age": 56, "id": "45355", "eye_color": "green", "wears_glasses": false}

Isso, contudo, não está muito legível, certo?

podemos melhorar a legibilidade da string em JSON adicionando indentação.

Para fazer isso automaticamente, somente precisamos passar um segundo argumento para especificar o número de espaços que queremos usar na indentação da string em JSON:

image-111
json.dumps(<obj>, indent=<spaces>), onde <spaces> são os espaços usados para indentação

💡 Dica: o segundo argumento tem de ser um número inteiro não negativo (número de espaços) ou uma string. Se a indentação for uma string (como "\t"), aquela string será usada para indentar cada nível (fonte).

Agora, se chamarmos dumps com esse segundo argumento:

client_JSON = json.dumps(client, indent=4)

O resultado da impressão de client_JSON será:

{
    "name": "Nora",
    "age": 56,
    "id": "45355",
    "eye_color": "green",
    "wears_glasses": false
}

Ficou muito melhor, certo? Agora, nossa string está formatada corretamente. Isso será muito útil quando quisermos começar a trabalhar com arquivos para armazenar os dados em um formato legível por seres humanos.

Como ordenar as chaves

Você também pode ordenar as chaves em ordem alfabética, se precisar. Para fazer isso, somente precisa escrever o nome do parâmetro sort_keys e passar o valor True:

image-84
json.dumps(<obj>, sort_keys=True), onde o valor True em sort_keys significa que as chaves devem ficar em ordem alfabética

💡 Dica: O valor de sort_keys é False por padrão se você não passar um valor.

Por exemplo:

client_JSON = json.dumps(client, sort_keys=True)

Isso retorna uma string com as chaves ordenadas alfabeticamente:

{"age": 56, "eye_color": "green", "id": "45355", "name": "Nora", "wears_glasses": false}

Como ordenar alfabeticamente e indentar (ao mesmo tempo)

Para gerar uma string em JSON que seja ordenada alfabeticamente e indentada, você precisa apenas passar os dois argumentos:

image-104

Neste caso, o resultado será:

{
    "age": 56,
    "eye_color": "green",
    "id": "45355",
    "name": "Nora",
    "wears_glasses": false
}

💡 Dica: você pode passar esses argumentos em qualquer ordem (em relação um ao outro), mas o objeto precisa ser o primeiro argumento da lista.

Bem, agora que você sabe como trabalhar com strings em JSON, vamos ver como você pode trabalhar com arquivos JSON em seus programas em Python.

🔸 JSON e arquivos

Tipicamente, o JSON é usado para armazenar dados em arquivos. Por isso, o Python nos dá as ferramentas de que precisamos para ler esses tipos de arquivo em nosso programa, trabalhar com seus dados e escrever dados novos.

💡 Dica: um arquivo JSON tem uma extensão .json:

image-62

Vamos ver como trabalhar com arquivos .json em Python.

Como ler um arquivo JSON em Python

Digamos que nós tenhamos criado o arquivo orders.json com esses dados, que representam dois pedidos em uma pizzaria:

{
	"orders": [ 
		{
			"size": "medium",
			"price": 15.67,
			"toppings": ["mushrooms", "pepperoni", "basil"],
			"extra_cheese": false,
			"delivery": true,
			"client": {
				"name": "Jane Doe",
				"phone": null,
				"email": "janedoe@email.com"
			}
		},
		{
			"size": "small",
			"price": 6.54,
			"toppings": null,
			"extra_cheese": true,
			"delivery": false,
			"client": {
				"name": "Foo Jones",
				"phone": "556-342-452",
				"email": null
			}
		}
	]
}
orders.json

Aproveite esse momento para analisar a estrutura desse arquivo JSON.

Aqui estão algumas dicas rápidas:

  • Observe os tipos de dados dos valores, a indentação e a estrutura geral do arquivo.
  • O valor da chave principal, "orders", é um array de objetos JSON (esse array será representado como uma lista em Python). Cada objeto JSON tem os dados de um pedido de pizza.

Se quisermos ler esse arquivo em Python, precisamos apenas usar a instrução with:

image-87
with open("orders.json") as file: data = json.load(file), onde open("orders.json") abre o arquivo orders.json em modo leitura, file é o objeto e json.load(file) lê o arquivo JSON "file" e cria um dicionário

💡 Dica: Na sintaxe acima, podemos atribuir qualquer nome a file (caixa verde). Essa é uma variável que podemos usar na instrução with para nos referirmos ao objeto "file" (arquivo).

A linha principal de código nessa sintaxe é:

data = json.load(file)
  • json.load(file) cria e retorna um novo dicionário em Python com os pares-chave-valor no arquivo JSON.
  • Depois, esse dicionário é atribuído à variável data.

💡 Dica: Observe que estamos usando load() em vez de loads(). Essa é uma função diferente no módulo json. Você aprenderá mais sobre as diferenças  entre eles ao final desse artigo.

Quando temos o conteúdo do arquivo JSON armazenado na variável data como um dicionário, podemos usá-lo para fazer, basicamente, o que quisermos.

Exemplos

Por exemplo, se escrevermos:

print(len(data["orders"]))

O resultado é 2, pois o valor da chave principal "orders" é uma lista com dois elementos.

Também podemos usar as chaves para acessar seus valores correspondentes. Isso é o que normalmente fazemos ao trabalhar com arquivos JSON.

Por exemplo, para acessar os sabores (toppings, em inglês) do primeiro pedido (order), escreveríamos:

data["orders"][0]["toppings"]
  • Primeiro, selecionamos a chave principal "orders"
  • Em seguida, selecionamos o primeiro elemento na lista (índice 0).
  • Por fim, selecionamos o valor que corresponde à chave "toppings"

Você pode ver esse "caminho" graficamente no diagrama abaixo:

image-101

Se imprimirmos esse valor, o resultado é:

['mushrooms', 'pepperoni', 'basil']

É exatamente aquilo que esperávamos. Você só precisa "mergulhar mais fundo" na estrutura do dicionário usando as chaves e índices necessários. É possível usar a string/arquivo JSON original como uma referência visual. Desse modo, você pode acessar, modificar ou excluir qualquer valor.

💡 Dica: Lembre-se de que estamos trabalhando com o novo dicionário. As alterações feitas a esse dicionário não afetarão o arquivo JSON. Para atualizar o conteúdo do arquivo, precisamos gravar os dados nele.

Como gravar dados em um arquivo JSON

Vamos ver como podemos gravar em um arquivo JSON.

A primeira linha da instrução with é bem semelhante. A única mudança é o fato de que você precisa abrir o arquivo em modo 'w' (write, ou gravação) para poder modificá-lo.

image-105
with open("orders.json", 'w') as file: data = json.load(file), onde o 'w' abre o objeto de arquivo 'file' em modo de gravação

💡 Dica: Se o arquivo já não existir no diretório (pasta) de trabalho atual, ele será criado automaticamente. Usando o modo 'w', substituiremos todo o conteúdo do arquivo se ele já existir.

Há duas alternativas para gravar em um arquivo JSON no corpo da instrução with:

  • dump
  • dumps

Vamos vê-las em detalhes.

Primeira abordagem: dump

Essa é uma função que recebe dois argumentos:

  • O objeto que será armazenado no formato JSON (por exemplo, um dicionário).
  • O arquivo onde ele será armazenado (um objeto de arquivo).
image-91
json.dump(<obj>, <file>), onde <obj> é o objeto a ser armazenado como JSON e <file> é o arquivo onde ele será armazenado

Digamos que a pizzaria quer remover os dados dos clientes do arquivo JSON e criar um novo arquivo JSON chamado orders_new.json com essa nova versão.

Podemos fazer isso com esse código:

# Abrir o arquivo orders.json
with open("orders.json") as file:
    # Carregar seu conteúdo e torná-lo um novo dicionário
    data = json.load(file)

    # Excluir o par chave-valor "client" de cada pedido
    for order in data["orders"]:
        del order["client"]

# Abrir (ou criar) um arquivo orders_new.json 
# e armazenar a nova versão dos dados.
with open("orders_new.json", 'w') as file:
    json.dump(data, file)

Essa era a versão original dos dados no arquivo orders.json. Observe que o par chave-valor "client" existe.

{
	"orders": [ 
		{
			"size": "medium",
			"price": 15.67,
			"toppings": ["mushrooms", "pepperoni", "basil"],
			"extra_cheese": false,
			"delivery": true,
			"client": {
				"name": "Jane Doe",
				"phone": null,
				"email": "janedoe@email.com"
			}
		},
		{
			"size": "small",
			"price": 6.54,
			"toppings": null,
			"extra_cheese": true,
			"delivery": false,
			"client": {
				"name": "Foo Jones",
				"phone": "556-342-452",
				"email": null
			}
		}
	]
}
orders.json

Essa é a nova versão no arquivo orders_new.json:

{"orders": [{"size": "medium", "price": 15.67, "toppings": ["mushrooms", "pepperoni", "basil"], "extra_cheese": false, "delivery": true}, {"size": "small", "price": 6.54, "toppings": null, "extra_cheese": true, "delivery": false}]}
orders_new.json

Se você analisar com cuidado, verá que o par chave-valor "client" foi removido de todos os pedidos.

No entanto, está faltando algo nesse arquivo, não é?

Pense um pouco a respeito... o que pode ser?

A indentação, é claro!

O arquivo não parece realmente com um arquivo JSON, mas podemos consertar isso facilmente passando o argumento indentation=4 para dump().

image-92
json.dump(<obj>, <file>, indent=4), onde 4 será a indentação

Agora, o conteúdo do arquivo terá essa aparência:

{
    "orders": [
        {
            "size": "medium",
            "price": 15.67,
            "toppings": [
                "mushrooms",
                "pepperoni",
                "basil"
            ],
            "extra_cheese": false,
            "delivery": true
        },
        {
            "size": "small",
            "price": 6.54,
            "toppings": null,
            "extra_cheese": true,
            "delivery": false
        }
    ]
}
orders_new.json

Que diferença! Essa seria exatamente a aparência esperada de um arquivo JSON.

Agora você sabe como ler e grava em arquivos JSON usando load() e dump(). Vamos ver as diferenças entre essas funções e as funções com as quais gostaríamos de trabalhar com as strings em JSON.

🔹 load() x loads()

Essa tabela resume as principais diferenças entre essas duas funções:

image-110
Enquanto load() cria um objeto em Python a partir de um arquivo JSON e tem como argumento um arquivo JSON, loads() cria um objeto em Python a partir de uma string e tem uma string como argumento. Ambos têm como valor de retorno um objeto em Python

💡 Dica: Imagine loads() como "LOAD (carregar) String" e isso ajudará você a se lembrar de qual função serve para qual finalidade.

🔸 dump() x dumps()

Aqui temos uma tabela que resume as diferenças principais entre essas duas funções:

image-109
Enquanto dump() grava um objeto em formato JSON em um arquivo tem como argumento o objeto e o arquivo, dumps() obtém uma string JSON a partir de um objeto e tem um objeto como argumento. dump() não tem valor de retorno, enquanto dumps() retorna uma string

💡 Dica: Imagine dumps() como "DUMP (gerar) String" e isso ajudará você a se lembrar de qual função serve para qual finalidade.

🔹 Terminologia importante em JSON

Por fim, há dois termos importantes que você precisa conhecer ao trabalhar com JSON:

  • Serialização: converter um objeto em uma string em JSON.
  • Desserialização: converter uma string em JSON em um objeto.

🔸 Em resumo

  • O JSON (JavaScript Object Notation) é um formato usado para representar e armazenar dados.
  • Ele é normalmente usado para transferir dados da web e armazenar definições de configuração.
  • Os arquivos JSON têm uma extensão .json.
  • Você pode converter strings em JSON em objetos em Python e vice-versa.
  • Você pode ler arquivos em JSON e criar objetos em Python a partir de seus pares chave-valor.
  • Você pode gravar em arquivos JSON para armazenar o conteúdo de objetos em Python em formato JSON.

Espero realmente que você tenha gostado desse artigo e que o tenha achado útil. Agora, você sabe como trabalhar com JSON em Python. Siga a autora no Twitter, @EstefaniaCassN, e confira os cursos on-line da autora (em inglês).