Manipulando JSON em Go
Durante a sua jornada como desenvolvedor em Go, você vai se deparar com alguns projetos que fazem o uso de arquivos .json
.
Nesta lição, você irá aprender tudo o que precisa saber sobre eles, desde o que eles são, como criá-los, e utilizar em seus projetos 😀
Criando seu projeto de testes
Dentro da pasta JornadaGoLang, nós iremos criar uma nova pasta chamada de 16-manipulando-json
, onde dentro dela, vamos criar o nosso arquivo main.go
:
package main
func main() {
}
Feito isso, vamos conhecer um pouco mais sobre os arquivos .json
😉
O que são arquivos JSON?
JSON
é um acrônimo para JavaScript Object Notation, que nada mais é do que um arquivo de notação feito em um formato leve de intercâmbio de dados.
Arquivos JSON
são fáceis de ler e de se escrever para nós humanos, ao mesmo tempo que é simples de ser interpretado pelas máquinas.
Tais arquivos são amplamente utilizados para o armazenamento e a transmissão de dados entre sistemas, especialmente em aplicações web e APIs.
Ou seja, arquivos .JSON
pode estar localizados localmente na sua máquina, como também podem ser passados entre sistemas web (por meio de requisições http e afins).
Como funciona a estrutura de um arquivo JSON?
O JSON
é baseado em dois tipos de estruturas:
- Objetos: Representados por um conjuntos de pares chave-valor, delimitados por
{}
. - Arrays: Representados por listas ordenadas de valores, delimitadas por
[]
.
Vejamos um exemplo bem simples de um JSON
representado por objetos:
{
"nome": "João",
"idade": 30,
"casado": false,
"hobbies": ["futebol", "leitura", "música"],
"endereco": {
"rua": "Av. Brasil",
"cidade": "São Paulo",
"cep": "01000-000"
}
}
Note que o formato JSON
é um formato fácil de ser lido, onde representam objetos no GoLang.
Creio que nesta altura do campeonato você já tenha mais ou menos uma ideia de como processá-los, não é verdade? Já que eles são bem similares aos maps
😉
Características de um JSON
Como vimos anteriormente, um JSON
nada mais é do que uma composição de objetos organizados em chave e valor.
Com relação às suas chaves e valores, ele suporta diversos tipos básicos, tais como:
string
,int
,float
,bool
,complex
- e etc...
Além disso, o JSON
pode conter objetos aninhados, como você mesmo viu no exemplo anterior:
"hobbies": ["futebol", "leitura", "música"]
Ah, e não se esqueça de utilizar vírgula para separar seus elementos, e dois pontos para associar chave-valor 😄
Vejamos um outro exemplo de um arquivo JSON
que começa com uma lista de objetos:
[
{
"nome": "Alice",
"idade": 25
},
{
"nome": "Bruno",
"idade": 30
},
{
"nome": "Carla",
"idade": 22
}
]
Perceba que ele começa com []
, em vez de {}
pois se trata de uma lista.
Onde o JSON pode ser usado?
Atualmente, o formato JSON
pode ter diversas aplicações no mundo da tecnologia.
Podemos usá-lo para trocar informações entre uma aplicação front-end e back-end por meio de APIs RESTful.
Ele também pode ser usados para o armazenamento de preferências do sistema e configurações de software (pode ser uma alternativa aos arquivos .env).
Além disso, podemos usar arquivos JSON
para a internacionalização da nossa aplicação (famosa tradução).
Agora que você já sabe tudo o que precisa saber sobre a anotação JSON
, vamos aprender a manipulá-lo usando GoLang 🙃
Importando a biblioteca encoding/json dentro do seu projeto
Por padrão, o GoLang já conta com uma biblioteca que é capaz de fazer a interpretação de um JSON
.
Essa biblioteca é chamada de enconding/json
, e pode ser incluída facilmente dentro do seu projeto da seguinte forma:
import "encoding/json"
Ou, caso você já tenha outras bibliotecas importadas, basta usar assim:
import (
"..."
"encoding/json"
)
Quando trabalhamos com essa biblioteca, os dados que foram lidos de um JSON
podem ser representados por:
- Structs (para dados estruturados)
- Mapas (
map[string]interface{}
) (para dados dinâmicos) - Slices (
[]interface{}
) (para listas)
Dito isso, vamos aprender a criar um JSON
😉
Criando um JSON a partir de uma struct
No GoLang, a melhor prática para se criar um JSON
, é a partir do mapeamento de uma struct
, observe:
package main
import (
"encoding/json"
"fmt"
)
type Pessoa struct {
Nome string `json:"nome"`
Idade int `json:"idade"`
}
func main() {
// Criando uma instância da struct
pessoa := Pessoa{Nome: "Alice", Idade: 25}
// Convertendo a struct para JSON
jsonBytes, err := json.Marshal(pessoa)
if err != nil {
fmt.Println("Erro ao converter para JSON:", err)
return
}
// Convertendo bytes para string e imprimindo
fmt.Println(string(jsonBytes))
}
Observe que estamos convertendo os dados da struct Pessoa
para a anotação JSON
usando a função Marshal
.
Lembrando que a tag json:"nome"
existente no struct
define o nome do campo no JSON
. Isso significa dizer que se você quer criar uma struct
que seja representada em JSON
, você sempre deverá fazer o uso dessas tags.
É importante ressaltar que a função Marshal
, converte os dados de uma struct
para a anotação JSON
, tanto é que se você der uma olhada no terminal, verá algo como:
{"nome":"Alice","idade":25}
O que indica que os nossos dados estão salvos em uma estrutura JSON
.
Para salvar essas informações em um arquivo .json
, basta seguir as explicações repassadas durante a lição que fala sobre manipulação de arquivos em Go.
Convertendo um JSON para uma struct (deserialização)
Deserialização nada mais é do que o ato de pegar uma anotação em JSON
e convertê-la de volta para uma struct
, map
ou array
, para que então, possamos ter acesso aos seus dados.
No GoLang, podemos fazer isso usando a função Unmarshal
da seguinte forma:
package main
import (
"encoding/json"
"fmt"
)
type Pessoa struct {
Nome string `json:"nome"`
Idade int `json:"idade"`
}
func main() {
// JSON de entrada (simulação de um arquivo ou API)
jsonData := `{"nome":"Alice","idade":25}`
// Criando uma variável para armazenar os dados
var pessoa Pessoa
// Convertendo JSON para struct
err := json.Unmarshal([]byte(jsonData), &pessoa)
if err != nil {
fmt.Println("Erro ao decodificar JSON:", err)
return
}
// Exibindo os dados
fmt.Println("Nome:", pessoa.Nome)
fmt.Println("Idade:", pessoa.Idade)
}
A saída será:
Nome: Alice
Idade: 25
Gravando um JSON em um Arquivo
O processo de gravação de um JSON
em um arquivo, pode ser obtido por meio da utilização da biblioteca os
, observe:
package main
import (
"encoding/json"
"fmt"
"os"
)
type Pessoa struct {
Nome string `json:"nome"`
Idade int `json:"idade"`
}
func main() {
// Criando uma struct
pessoa := Pessoa{Nome: "Bruno", Idade: 30}
// Criando o arquivo
file, err := os.Create("pessoa.json")
if err != nil {
fmt.Println("Erro ao criar o arquivo:", err)
return
}
defer file.Close()
// Criando o encoder e escrevendo no arquivo
encoder := json.NewEncoder(file)
err = encoder.Encode(pessoa)
if err != nil {
fmt.Println("Erro ao escrever JSON:", err)
return
}
fmt.Println("Arquivo JSON salvo com sucesso!")
}
No exemplo acima, será criado um arquivo chamado pessoa.json
, dentro da mesma pasta onde está localizado seu arquivo main.go
.
A função json.NewEncoder(file).Encode(pessoa)
é responsável por realizar a gravação desses dados.
Lendo um JSON de um Arquivo
Agora, vamos aprender a realizar a gravação de um arquivo JSON
👾
package main
import (
"encoding/json"
"fmt"
"os"
)
type Pessoa struct {
Nome string `json:"nome"`
Idade int `json:"idade"`
}
func main() {
// Abrindo o arquivo
file, err := os.Open("pessoa.json")
if err != nil {
fmt.Println("Erro ao abrir o arquivo:", err)
return
}
defer file.Close()
// Criando uma variável para armazenar os dados
var pessoa Pessoa
// Criando um decoder e lendo os dados do arquivo
decoder := json.NewDecoder(file)
err = decoder.Decode(&pessoa)
if err != nil {
fmt.Println("Erro ao ler JSON:", err)
return
}
// Exibindo os dados
fmt.Println("Nome:", pessoa.Nome)
fmt.Println("Idade:", pessoa.Idade)
}
Note que usamos a biblioteca os
para salvar este arquivo em conjunto com um nome especificado.
Manipulando JSONs dinâmicamente
Anteriormente, você aprendeu a manipular arquivos JSON
nas quais seus índices (chaves) já eram conhecidos.
Porém, nem sempre você vai saber de todos os campos que um JSON
poderá retornar.
Em casos como estes, se o JSON
for desconhecido ou tiver campos variáveis, você pode usar um map[string]interface{}
para fazer a leitura automática, observe:
package main
import (
"encoding/json"
"fmt"
)
func main() {
// JSON desconhecido
jsonData := `{"nome":"Carlos","idade":40,"profissao":"Engenheiro"}`
// Criando um mapa para armazenar os dados
var data map[string]interface{}
// Convertendo JSON para mapa
err := json.Unmarshal([]byte(jsonData), &data)
if err != nil {
fmt.Println("Erro ao decodificar JSON:", err)
return
}
// Exibindo os valores
fmt.Println("Nome:", data["nome"])
fmt.Println("Idade:", data["idade"])
fmt.Println("Profissão:", data["profissao"])
}
Note que o comando map[string]interface{}
permite armazenar qualquer tipo de dado em JSON
.
E como você já deve saber, basta usar data["chave"]
para acessar os valores do map
😉
Mas e se o JSON for uma lista de objetos desconhecidos?
Bem, neste caso, é recomendável que você faça o uso de um slice
([]map[string]interface{}
) para representar cada item de um map
:
package main
import (
"encoding/json"
"fmt"
)
func main() {
// JSON com uma lista de objetos
jsonData := `[{"nome":"Carlos","idade":40,"profissao":"Engenheiro"},
{"nome":"Maria","idade":35,"profissao":"Médica"},
{"nome":"João","idade":28}]`
// Criando um slice de maps
var pessoas []map[string]interface{}
// Convertendo JSON para slice de mapas
err := json.Unmarshal([]byte(jsonData), &pessoas)
if err != nil {
fmt.Println("Erro ao decodificar JSON:", err)
return
}
// Iterando sobre os objetos do JSON
for i, pessoa := range pessoas {
fmt.Println("Pessoa", i+1)
fmt.Println("Nome:", pessoa["nome"])
fmt.Println("Idade:", pessoa["idade"])
// Profissão pode não existir em todos os objetos
if profissao, existe := pessoa["profissao"]; existe {
fmt.Println("Profissão:", profissao)
} else {
fmt.Println("Profissão: Não informada")
}
fmt.Println("----------------------")
}
}
A saída será:
Pessoa 1
Nome: Carlos
Idade: 40
Profissão: Engenheiro
----------------------
Pessoa 2
Nome: Maria
Idade: 35
Profissão: Médica
----------------------
Pessoa 3
Nome: João
Idade: 28
Profissão: Não informada
----------------------
- Criamos um
slice
demap[string]interface{}
para lidar com listas. - Utilizamos
json.Unmarshal()
para converter oJSON
para Go. - Utilizamos
json.Unmarshal()
para converter oJSON
para Go. - Iteramos sobre o
slice
para acessar cada objeto. - Verificamos se a chave
"profissao"
existe antes de exibi-la.
Trabalhando com Listas em JSON (Array)
Caso você tenha certeza de que o JSON
é uma lista, você pode fazer o uso de um slice
de structs
da seguinte forma:
package main
import (
"encoding/json"
"fmt"
)
type Pessoa struct {
Nome string `json:"nome"`
Idade int `json:"idade"`
}
func main() {
// JSON de uma lista de pessoas
jsonData := `[{"nome":"Ana","idade":20},{"nome":"Pedro","idade":35}]`
// Criando um slice para armazenar os dados
var pessoas []Pessoa
// Convertendo JSON para slice de structs
err := json.Unmarshal([]byte(jsonData), &pessoas)
if err != nil {
fmt.Println("Erro ao decodificar JSON:", err)
return
}
// Exibindo os dados
for _, pessoa := range pessoas {
fmt.Println("Nome:", pessoa.Nome, "| Idade:", pessoa.Idade)
}
}
A saída será:
Nome: Ana | Idade: 20
Nome: Pedro | Idade: 35
Reconhecendo se o JSON é um array ou um objeto
Antes de fazer o parse (ato de transformar um JSON em um array, map ou slice) de um JSON
em Go, podemos verificar se ele é uma lista (array
) ou um objeto (map
).
Isso é útil para garantir que estamos manipulando os dados corretamente sem gerar erros.
Atualmente, nós podemos fazer isso de duas formas:
- Usando
json.Unmarshal()
cominterface{}
etype assertion
(switch
) - Usando
json.Decoder().Token()
para analisar a estrutura
Método 1: json.Unmarshal() com Type Assertion
No comando abaixo estamos usando o Unmarshal com Type Assertion para identificar um JSON:
package main
import (
"encoding/json"
"fmt"
)
func detectarJSON(jsonData []byte) {
// Criamos uma variável do tipo `interface{}` para armazenar os dados
var temp interface{}
// Fazemos o parse do JSON
err := json.Unmarshal(jsonData, &temp)
if err != nil {
fmt.Println("Erro ao fazer o parse do JSON:", err)
return
}
// Verificamos o tipo da estrutura usando type assertion
switch temp.(type) {
case []interface{}:
fmt.Println("O JSON é uma LISTA (array).")
case map[string]interface{}:
fmt.Println("O JSON é um OBJETO (map).")
default:
fmt.Println("Formato desconhecido.")
}
}
func main() {
// JSON de exemplo (lista)
jsonLista := []byte(`[{"nome": "Carlos", "idade": 40}, {"nome": "Maria", "idade": 35}]`)
// JSON de exemplo (objeto)
jsonObjeto := []byte(`{"empresa": "TechCorp", "fundacao": 1999}`)
fmt.Println("Detectando JSON Lista:")
detectarJSON(jsonLista)
fmt.Println("\nDetectando JSON Objeto:")
detectarJSON(jsonObjeto)
}
- Usamos
json.Unmarshal()
para converter oJSON
eminterface{}
. - Em seguida, usamos um
switch
para verificar se o tipo resultante é[]interface{}
(lista) oumap[string]interface{}
(objeto). - Se o
JSON
não for nenhum dos dois, exibimos "Formato desconhecido".
Método 2: Usando json.Decoder().Token()
Outra forma de verificar a estrutura do JSON
sem carregar todos os dados na memória é usar o primeiro token
lido pelo json.Decoder()
:
package main
import (
"encoding/json"
"fmt"
"strings"
)
func detectarJSONComDecoder(jsonData string) {
// Criamos um decoder para processar o JSON em stream
decoder := json.NewDecoder(strings.NewReader(jsonData))
// Pegamos o primeiro token do JSON
token, err := decoder.Token()
if err != nil {
fmt.Println("Erro ao ler JSON:", err)
return
}
// Verificamos se o primeiro token é um '[' (lista) ou '{' (objeto)
switch token {
case json.Delim('['):
fmt.Println("O JSON é uma LISTA (array).")
case json.Delim('{'):
fmt.Println("O JSON é um OBJETO (map).")
default:
fmt.Println("Formato desconhecido.")
}
}
func main() {
// JSON de exemplo (lista)
jsonLista := `[{"nome": "Carlos", "idade": 40}, {"nome": "Maria", "idade": 35}]`
// JSON de exemplo (objeto)
jsonObjeto := `{"empresa": "TechCorp", "fundacao": 1999}`
fmt.Println("Detectando JSON Lista:")
detectarJSONComDecoder(jsonLista)
fmt.Println("\nDetectando JSON Objeto:")
detectarJSONComDecoder(jsonObjeto)
}
- O
json.Decoder().Token()
lê apenas o primeiro caractere significativo doJSON
. - Se for
'['
, sabemos que oJSON
é uma lista. - Se for
'{'
, sabemos que é um objeto.
Esse método é mais eficiente, pois não precisa carregar o JSON
inteiro na memória.
Verificando se um JSON é válido
Haverão momentos em que por obra de erros de softwares, ou de desenvolvedores desapercebidos, um JSON
pode ser inválido.
Pode ser inválido por diversos motivos, tais como erros de software ou desenvolvedores que se esqueceram de fechar uma tag, e que por conta disso, ocasionou erros na leitura desses arquivos.
Por exemplo:
[
{
"nome: "Alice",
"idade": 25
},
{
"nome": "Bruno",
"idade": 30
}
{
"nome": "Carla",
"idade": 22
}
O JSON
acima tem 3 problemas:
- A primeira chave nome, não está fechada corretamente:
"nome: "Alice"
, - O segundo objeto da lista não possuí uma vírgula
}
- O final do arquivo carece de um
]
, o que indica que a lista não foi fechada corretamente.
Durante a sua jornada como desenvolvedor, é bem provável que você vá encontrar muitos erros assim, o que pode ocasionar um erro de leitura.
E foi pensando nisso, que existe a função valid()
da biblioteca encoding/json
, que é capaz de validar se o JSON
é válido ou não:
package main
import (
"encoding/json"
"fmt"
)
func verificarJSON(jsonData []byte) {
if json.Valid(jsonData) {
fmt.Println("✅ O JSON é válido!")
} else {
fmt.Println("❌ O JSON é inválido!")
}
}
func main() {
// JSON válido (Objeto)
jsonValido := []byte(`{"nome": "Carlos", "idade": 30}`)
// JSON válido (Lista)
jsonListaValida := []byte(`[{"nome": "Ana"}, {"nome": "Pedro"}]`)
// JSON inválido (chave sem aspas e falta de vírgula)
jsonInvalido := []byte(`{nome: "Carlos" "idade": 30}`)
// JSON inválido (falta de fechamento do colchete)
jsonListaInvalida := []byte(`[{"nome": "Ana", "idade": 25}`)
fmt.Println("Verificando JSON Objeto:")
verificarJSON(jsonValido)
fmt.Println("\nVerificando JSON Lista:")
verificarJSON(jsonListaValida)
fmt.Println("\nVerificando JSON Inválido (Objeto):")
verificarJSON(jsonInvalido)
fmt.Println("\nVerificando JSON Inválido (Lista):")
verificarJSON(jsonListaInvalida)
}
O comando json.Valid(jsonData)
irá retornar true
se o JSON
estiver corretamente formatado.
Caso o JSON
tenha erros, a função retorna false
, permitindo que você trate isso antes de tentar fazer json.Unmarshal()
.
Adicionando, atualizando e removendo valores de um JSON
Nem sempre, você fará o uso de um JSON
somente para consultar (ler) seus valores. Existirão casos, em você você vai precisar adicionar, atualizar e até mesmo remover valores de um JSON
.
Em casos como estes, podemos usar slices ([]
) e mapas (map[string]interface{}
) antes de salvar o JSON
atualizado no arquivo.
Veremos abaixo um passo a passo de como isso pode ser feito 🥳
📌 Estrutura do Exemplo
Vamos trabalhar com um JSON
representando uma lista de pessoas, onde cada pessoa tem nome
, idade
e, opcionalmente uma profissao
.
[
{"nome": "Carlos", "idade": 40, "profissao": "Engenheiro"},
{"nome": "Maria", "idade": 35, "profissao": "Médica"},
{"nome": "João", "idade": 28}
]
Considerado que essa anotação está salva em uma arquivo chamado pessoas.json
que existe na mesma pasta de onde está seu arquivo main.go
, podemos prosseguir para a leitura do mesmo.
📂 1. Abrindo e Lendo um JSON de um Arquivo
Antes de manipular os dados, precisamos carregá-los de um arquivo:
package main
import (
"encoding/json"
"fmt"
"os"
)
func lerArquivoJSON(caminho string) ([]map[string]interface{}, error) {
// Abrindo o arquivo
file, err := os.Open(caminho)
if err != nil {
return nil, err
}
defer file.Close()
// Criando um slice de mapas para armazenar os dados
var pessoas []map[string]interface{}
// Decodificando o JSON para o slice
decoder := json.NewDecoder(file)
err = decoder.Decode(&pessoas)
if err != nil {
return nil, err
}
return pessoas, nil
}
No momento, criamos apenas uma função chamada lerArquivoJSON
que recebe um caminho, e retorna um slice
de mapas.
📝 2. Adicionando um Novo Objeto ao JSON
Com o arquivo aberto, você pode criar uma função especifica que será responsável por adicionar novas pessoas ao JSON
:
func adicionarPessoa(pessoas *[]map[string]interface{}, nome string, idade int, profissao string) {
novaPessoa := map[string]interface{}{
"nome": nome,
"idade": idade,
}
// Adicionando a profissão se não for vazia
if profissao != "" {
novaPessoa["profissao"] = profissao
}
// Adicionando ao slice
*pessoas = append(*pessoas, novaPessoa)
}
Note que no exemplo acima, criamos um map[string]interface{}
para armazenar os novos dados.
Caso a profissao
for informada, ela é adicionada de forma automática dentro do mapa.
Observe também que fizemos o uso do append()
para incluir a nova pessoa na lista.
✏️ 3. Atualizando um Objeto no JSON
O processo de atualização também é bem fácil, basta ter o map
em mãos, percorrer a lista, encontrar o item e fazer a modificação, observe:
func atualizarPessoa(pessoas *[]map[string]interface{}, nome string, novaIdade int, novaProfissao string) bool {
for i, pessoa := range *pessoas {
if pessoa["nome"] == nome {
(*pessoas)[i]["idade"] = novaIdade
if novaProfissao != "" {
(*pessoas)[i]["profissao"] = novaProfissao
}
return true
}
}
return false
}
No exemplo acima, se encontrarmos o nome
informado, atualizamos sua idade
e profissao
.
Por fim, retornamos true
ou false
, em caso da pessoa ter sido encontrada ou não.
❌ 4. Removendo um Objeto do JSON
Para remover um item da lista, é bem simples, tudo o que você precisa fazer é criar um novo slice
sem o elemento desejado:
func removerPessoa(pessoas *[]map[string]interface{}, nome string) bool {
for i, pessoa := range *pessoas {
if pessoa["nome"] == nome {
// Removendo o item do slice
*pessoas = append((*pessoas)[:i], (*pessoas)[i+1:]...)
return true
}
}
return false
}
No exemplo acima, buscamos um índice da pessoa a ser removida.
Em seguida usamos um slicing (append(slice[:i], slice[i+1:]...)
) para excluir tal item da lista.
💾 5. Salvando as Alterações no Arquivo
Por fim, não podemos nos esquecer de criar a última função, e não menos importante, que será responsável por salvar nossos dados em um JSON
:
func salvarArquivoJSON(caminho string, pessoas []map[string]interface{}) error {
// Criando o arquivo (ou sobrescrevendo)
file, err := os.Create(caminho)
if err != nil {
return err
}
defer file.Close()
// Criando um encoder para escrever o JSON no arquivo
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ") // Indentação para melhor visualização
return encoder.Encode(pessoas)
}
Lembrando que usamos o comando json.NewEncoder(file).Encode(pessoas)
para salvar os dados formatados.
🚀 6. Testando Todas as Funcionalidades
Agora que já criamos todas as funções necessárias, vamos criar a nossa função main()
onde vai conter todas as chamadas de ler, adicionar, atualizar, remover e salvar o JSON.
package main
import (
"encoding/json"
"fmt"
"os"
)
func lerArquivoJSON(caminho string) ([]map[string]interface{}, error) {
file, err := os.Open(caminho)
if err != nil {
return nil, err
}
defer file.Close()
var pessoas []map[string]interface{}
decoder := json.NewDecoder(file)
err = decoder.Decode(&pessoas)
if err != nil {
return nil, err
}
return pessoas, nil
}
func adicionarPessoa(pessoas *[]map[string]interface{}, nome string, idade int, profissao string) {
novaPessoa := map[string]interface{}{
"nome": nome,
"idade": idade,
}
if profissao != "" {
novaPessoa["profissao"] = profissao
}
*pessoas = append(*pessoas, novaPessoa)
}
func atualizarPessoa(pessoas *[]map[string]interface{}, nome string, novaIdade int, novaProfissao string) bool {
for i, pessoa := range *pessoas {
if pessoa["nome"] == nome {
(*pessoas)[i]["idade"] = novaIdade
if novaProfissao != "" {
(*pessoas)[i]["profissao"] = novaProfissao
}
return true
}
}
return false
}
func removerPessoa(pessoas *[]map[string]interface{}, nome string) bool {
for i, pessoa := range *pessoas {
if pessoa["nome"] == nome {
*pessoas = append((*pessoas)[:i], (*pessoas)[i+1:]...)
return true
}
}
return false
}
func salvarArquivoJSON(caminho string, pessoas []map[string]interface{}) error {
file, err := os.Create(caminho)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ") // Indentação para melhor visualização
return encoder.Encode(pessoas)
}
func main() {
// Caminho do arquivo JSON
caminho := "pessoas.json"
// Ler o arquivo JSON
pessoas, err := lerArquivoJSON(caminho)
if err != nil {
fmt.Println("Erro ao ler JSON:", err)
return
}
// Adicionar uma nova pessoa
adicionarPessoa(&pessoas, "Lucas", 27, "Designer")
// Atualizar uma pessoa
atualizarPessoa(&pessoas, "Carlos", 41, "Gerente de Engenharia")
// Remover uma pessoa
removerPessoa(&pessoas, "Maria")
// Salvar alterações no arquivo
err = salvarArquivoJSON(caminho, pessoas)
if err != nil {
fmt.Println("Erro ao salvar JSON:", err)
return
}
fmt.Println("Alterações salvas com sucesso!")
}
Incrível, não acha?
Repositório da lição
Todos os arquivos relacionados com esta lição, podem ser encontrados nos seguintes repositórios abaixo:
Conclusão
Nesta lição, você aprendeu a manipular arquivos JSON
de diversas formas diferentes:
✅ Como converter um JSON para struct
✅ Como salvar e ler JSONs em arquivos
✅ Como manipular JSONs dinâmicos com map[string]interface{}
✅ Como lidar com listas de JSON
✅ Como adicionar novos itens a um JSON
✅ Como atualizar valores existentes
✅ Como remover um objeto de uma lista JSON
✅ Como salvar o JSON atualizado no arquivo
Assuntos suficientes para que você possa dominar a manipulação de JSONs
em qualquer projeto! 🚀
Até a próxima lição.