Back-End

18 mar, 2019

Golang: como ler um arquivo json

Publicidade

Na web, o JSON é conhecido como um dos principais formatos de reapresentação de dados, e sua fama se dá ao fato de ele ser leve (compare com o formato XML pra ver), simples e compacto, facilitando o parsing das informações pela aplicação.

A verdade é que já existem muitas formas de ler um arquivo JSON usando o golang, mas hoje vamos restringir o nosso estudo a um parsing usando apenas o pacotes da biblioteca padrão da linguagem (o GO tem milhares de pacotes ‘nativos’, por assim dizer, que facilitam nossa vida mantendo o programa leve).

Vamos lá!

Pré-requisitos: vamos partir do pressuposto de que você já esteja ciente da instalação do GO em sua máquina, beleza? Caso não tenha instalado ainda, dê uma olhada nesses artigos bacanas:

Ou ainda na documentação oficial que – pasmem – está em português, e faça a instalação antes de começarmos.

Passo 1 – Ferramentas

Para esse artigo vamos usar as seguintes ferramentas:

  • GO Versão 1.12+ (na minha máquina é essa, mas você pode utilizar a versão mais atual também)
  • Visual Code
  • Packages GO: digitar a instrução go get para baixar os pacotes

Passo 2 – Estrutura de um programa em GO

Os programas em GO devem ser criados dentro da pasta source, definida na instalação, que por padrão é “C:\Users\nome-do-seu-usuario\go\src”. Dentro dessa pasta vamos criar uma pasta chamada go-read-json-file.

Todo programa em go precisa de um arquivo inicial, conhecido como main, que vai ser executado ao inicializarmos a aplicação.

Aqui vamos exemplificar com esse arquivo, mas todo arquivo em go tem basicamente a mesma estrutura, que é essa abaixo:

Estrutura dos arquivos em Go

package main //nome do package. Como estamos na raiz do programa o nome da package será "main"

import (
	//Declaração de todos os pacotes que serão utilizados nesse arquivo
)

func main() {
	//Instruções iniciais da aplicação.
}

Pois bem, vamos entrar dentro dessa pasta a partir do Visual Studio Code e criar um novo arquivo chamado main.go, onde vai ficar todo nosso código.

Passo 3 – Conhecendo a estrutura do JSON

Vamos trabalhar com um objeto bem simples (por enquanto, muHAhaAHhah), que vai conter algumas propriedades de um objeto livro, conforme apresentado no trecho abaixo:

{
    "name":"Programando em Go: Crie aplicações com a linguagem do Google",
    "publisher":"Casa do código", 
    "author": "Caio Filipini", 
    "link":"https://www.casadocodigo.com.br/products/livro-google-go"
}

Passo 4 – Criando o objeto em GO

Para converter essa estrutura JSON para uma struct – é assim que chamamos classes em GO – podemos usar a ferramenta JSON-to-Go.

Basta colar o json lá que ela converte para o formato de classe do GO rapidinho, precisando apenas ajustar seu nome ou quebrar em mais structs, se necessário.

Book: nossa primeira struct 

type Book struct {
	Name      string `json:"name"`
	Publisher string `json:"publisher"`
	Author    string `json:"author"`
	Link      string `json:"link"`
}

Passo 5 – Abrindo o arquivo JSON

Pacotes

Aqui vamos usar a função Open do pacote nativo os. Para utilizarmos os pacotes no Golang basta importarmos o pacote através da instrução abaixo:

Exemplos de imports em golang

import (
	"nome_do_pacote"    			 //pacote nativo
	"https://github.com/user/nome_do_pacote" //pacote da comunidade - endereço completo do pacote
)

Aqui nessa POC vamos trabalhar apenas com pacotes nativos, conforme a imagem abaixo:

Import dos pacotes nativos que vamos usar

import (
	"fmt"
	"io/ioutil"
	"os"
	"encoding/json"
)

No trecho abaixo estamos abrindo nosso arquivo JSON através da função os.Open, que além de retornar o arquivo jsonFile, retorna um objeto do tipo error, para que seja possível verificar se houve algum erro na abertura do arquivo:

jsonFile, err := os.Open(`book.json`)

Error

É sempre importante verificar se ocorreram erros durante a execução do nosso programa. Aqui vamos fazer uma verificação simples, apenas apresentando o erro na tela, caso ocorra o erro. Conforme a instrução a seguir:

if err != nil {
		//Caso tenha tido erro, ele é apresentado na tela
		fmt.Println(err)
	}

Esse trecho será usado sempre que as funções retornarem erros para podermos realizar alguma tratativa em relação a eles.

Dispose e Defer

Uma boa prática é sempre fechar, ou dar dispose, nos objetos que utilizamos, para não ocuparmos memória, tão pouco recursos de I/O, desnecessários durante a execução do programa.

Algumas linguagens possuem um funcionalidade chamada em geral de “Garbage Collector”, que é um tipo de lixeiro que passa de vez em quando para limpar a memória. O GO também possui esse recurso para gerenciar a memória.

Contudo, não existe essa funcionalidade para a gestão de recursos de I/O, como conexão de rede, conexão de banco de dados ou arquivos físicos. Para fazer isso temos um instrução que auxilia nessa finalidade: o defer. Essa instrução é executada no fim de cada função com o bloco de código que inserirmos. Com o código abaixo fechamos o arquivo “jsonFile” ao fim da função.

defer jsonFile.Close()

Passo 6 – Decodificando o JSON para nosso objeto

Para conseguir manipular o nosso json dentro de um objeto Book, vamos precisar transformar nosso arquivo primeiro em um array de bytes para depois utilizar a função json.Unmarshal para transformar os bytes em um objeto Book. No código é exatamente o que estamos fazendo.

	//Aqui o arquivo é convertido para uma variável array de bytes, através do pacote "io/ioutil"
	byteValueJSON, _:= ioutil.ReadAll(jsonFile)

	//Declaração abreviada de um objeto do tipo Book
	objBook := Book{}

	//Conversão da variável byte em um objeto do tipo struct Book
	json.Unmarshal(byteValueJSON, &objBook)

Passo 7 – Alterando o objeto Book

A alteração de uma propriedade em GO é super simples e parecida com muitas linguagens. Basta usar a instrução “nome_do_objeto.nome_da_propriedade”. Segue um exemplo para alterarmos e vermos a alteração da propriedade no console:

Antes e depois da propriedade Name do objeto objBook

//Apresentação na tela do campo Name
fmt.Println(objBook.Name)	

//Alteração do campo Name
objBook.Name = "New book name"

//Apresentação no console do novo valor do campo Name
fmt.Println(objBook.Name)	

Vamos executar o programa agora pra ver essa alteração no console. Para isso, digite a seguinte alteração no console: go run main.go.

Passo 8 – Salvando em um arquivo JSON

Agora, para finalizar com chave de ouro, vamos salvar nossa struct alterada em um novo arquivo? Vamos!

Para isso basta converter o objeto objBook para um array de bytes usando a função json.Marshal, e depois, através da função ioutil.WriteFile, salvar em um novo arquivo.

//Aqui vamos converter nosso objBook com o nome alterado em bytes
byteValueJSON, err = json.Marshal(objBook)
if err != nil {
  fmt.Println(err)
}

//Por fim vamos salvar em um arquivo JSON alterado.
err = ioutil.WriteFile("newBook.json", byteValueJSON, 0644)
if err != nil {
  fmt.Println(err)
}

Usei o nome newBook.json para não sobrescrever o arquivo original. Sempre que executar sua aplicação, o arquivo newBook.json será sobrescrito.

Arquivo JSON sendo criado

Extras

Se quiser se aprofundar nos packages de manipulação de json, dê uma olhada nesses links:

E fim! Sua primeira aplicação em GO está finalizada! Caso queira consultar o código, subi um repo no GIT com a solução (com o comentário de cada linha de código).

Espero que tenha ajudado, e se tiver alguma dúvida ou sugestão, deixe nos comentários.

Até mais!