6.4. Leitura e Escrita de Arquivos JSON em Python

A biblioteca padrão do Python possui um módulo denominado json que pode ser utilizado para manipulação de documentos JSON. A forma mais simples de trabalhar este formato é através da representação de dicionários do Python, que possui uma mapeamento direto com o tipo object da notação JSON. Para começar nosso exercício com a manipulação de textos no formato JSON, vamos importar a biblioteca JSON e transformar um dicionário em um documento no formato JSON:

Trecho de Código 6.1 - Transformando um dicionário Python em um documento JSON.
 1import json
 2
 3endereco = {
 4    'rua': 'Av. dos Astronautas',
 5    'numero': 1758,
 6    'bairro': 'Jardim da Granja',
 7    'cidade': 'São José dos Campos',
 8    'UF': 'SP',
 9    'CEP': '12227-010'
10}
11
12endereco_json = json.dumps(endereco)
13
14print(endereco_json)

Repare no trecho de programa acima, que o identificador endereco_json fica associado a uma string contendo todo o texto do documento JSON equivalente ao dicionário informado na função json.dumps. Esse processo de transformar um objeto Python em um documento texto é conhecido por serialização.

De maneira similar, podemos ler um texto representando um documento JSON e transformá-lo em um dicionário Python, através da função json.loads:

Trecho de Código 6.2 - Transformando um documento JSON em um dicionário Python.
 1import json
 2
 3doc = '{"rua": "Av. dos Astronautas", "numero": 1758, \
 4      "bairro": "Jardim da Granja", \
 5      "cidade": "S\\u00e3o Jos\\u00e9 dos Campos", \
 6      "UF": "SP", "CEP": "12227-010"}'
 7
 8endereco = json.loads(doc)
 9
10print( endereco['rua'] )
11print( endereco['numero'] )
12print( endereco['cidade'] )

No trecho de código acima podemos observar que após transformar a string contendo o texto do documento JSON (doc) em um dicionário Python através da função json.loads, podemos acessar os valores associados às chaves rua, numero e cidade no dicionário (endereco). Este processo de transformar um documento texto em um objeto Python é chamado de deserialização.

Agora vamos ler um documento JSON.

Trecho de Código 6.3 - Documento JSON com informações sobre uma publicação científica (artigo.json).
{
  "indexed": {
    "date-parts": [ [2020, 4, 17] ],
    "date-time": "2020-04-17T06:23:05Z",
    "timestamp": 1587104585191
  },
  "reference-count": 55,
  "publisher": "MDPI AG",
  "issue": "8",
  "license": [
    {
      "URL": "https://creativecommons.org/licenses/by/4.0/",
      "start": {
        "date-parts": [ [2020, 4, 16] ],
        "date-time": "2020-04-16T00:00:00Z",
        "timestamp": 1586995200000
      }
    }
  ],
  "abstract": "In recent years, Earth observation (EO) satellites...",
  "DOI": "10.3390/rs12081253",
  "type": "article-journal",
  "created": {
    "date-parts": [ [2020, 4, 16] ],
    "date-time": "2020-04-16T17:01:39Z",
    "timestamp": 1587056499000
  },
  "page": "1253",
  "source": "Crossref",
  "is-referenced-by-count": 0,
  "title": "An Overview of Platforms for Big Earth Observation Data Management and Analysis",
  "prefix": "10.3390",
  "volume": "12",
  "author": [
    {
      "ORCID": "http://orcid.org/0000-0003-3239-2160",
      "authenticated-orcid": false,
      "given": "Vitor C. F.",
      "family": "Gomes",
      "sequence": "first",
      "affiliation": []
    },
    {
      "ORCID": "http://orcid.org/0000-0001-7534-0219",
      "authenticated-orcid": false,
      "given": "Gilberto R.",
      "family": "Queiroz",
      "sequence": "additional",
      "affiliation": []
    },
    {
      "ORCID": "http://orcid.org/0000-0003-2656-5504",
      "authenticated-orcid": false,
      "given": "Karine R.",
      "family": "Ferreira",
      "sequence": "additional",
      "affiliation": []
    }
  ],
  "member": "1968",
  "published-online": { "date-parts": [ [2020, 4, 16] ] },
  "container-title": "Remote Sensing",
  "original-title": [],
  "language": "en",
  "link": [{
    "URL": "https://www.mdpi.com/2072-4292/12/8/1253/pdf",
    "content-type": "unspecified",
    "content-version": "vor",
    "intended-application": "similarity-checking"
  }],
  "deposited": {
    "date-parts": [ [2020, 4, 16] ],
    "date-time": "2020-04-16T17:51:19Z",
    "timestamp": 1587059479000
  },
  "score": 1.0,
  "subtitle": [],
  "short-title": [],
  "issued": {
    "date-parts": [ [2020, 4, 16] ]
  },
  "references-count": 55,
  "journal-issue": {
    "published-online": {
      "date-parts": [ [2020, 4] ]
    },
    "issue": "8"
  },
  "alternative-id": ["rs12081253"],
  "URL": "http://dx.doi.org/10.3390/rs12081253",
  "ISSN": ["2072-4292"],
  "subject": ["General Earth and Planetary Sciences"],
  "container-title-short": "Remote Sensing"
}

Podemos ler o arquivo artigo.json utilizando a função interna do Python chamada open(), como mostrado abaixo:

Trecho de Código 6.4 - Leitura de um documento JSON.
1import json
2
3with open( 'artigo.json', 'r' ) as arq_json:
4    artigo = json.load( arq_json )
5
6    print( artigo['title'] )
7
8    for autor in artigo['author']:
9        print( 'Nome: {} {}'.format(autor['given'], autor['family']) )

Repare que após a abertura do arquivo na linha 03, realizamos a leitura dos dados deste arquivo na linha 04 através da função json.load(). Após a transformação do arquivo em um dicionário Python, podemos acessar os campos desse dicionário usando o operador [], recuperando assim o título do artigo e sua lista de autores.

Para gravar um arquivo JSON podemos usar a função json.dump como mostrado no trecho de código abaixo:

Trecho de Código 6.5 - Escrita de um documento JSON.
 1import json
 2
 3endereco = {
 4    'rua': 'Av. dos Astronautas',
 5    'numero': 1758,
 6    'bairro': 'Jardim da Granja',
 7    'cidade': 'São José dos Campos',
 8    'UF': 'SP',
 9    'CEP': '12227-010'
10}
11
12with open('endereco.json', 'w') as arq_json:
13    json.dump(endereco, arq_json)

Após a execução do trecho de código acima, você deverá ter um arquivo chamado endereco.json contendo a serialização do dicionário Python endereco na forma de um arquivo JSON.

Nota

As funções json.dump e json.dumps aceitam um argumento nomeado, indent, que pode ser usado para controlar a indentação do documento JSON. Na linha 14 do trecho de código acima, poderíamos utilizar um nível de indentação com 4 espaços:

json.dump(endereco, arq_json, indent=4)

Nota

Mais detalhes sobre leitura/escrita de arquivos JSON podem ser encontrados em [16], [28] e [30].