Como converter Go struct em JSON: do iniciante ao profissional
Trabalhar com JSON é o pão de cada dia para qualquer desenvolvedor backend em Go. Praticamente todos os dias você precisa enviar dados para o cliente, receber requisições de API ou salvar configurações. E em 90% dos casos, isso é JSON. Mas como transformar corretamente sua struct nativa em JSON legível? Parece simples, não? No entanto, o diabo está nos detalhes: tags incorretas, campos vazios, erros esquecidos — e de repente sua API retorna algo errado.
Neste artigo, abordaremos a conversão de Go struct em JSON desde o básico até técnicas avançadas. Você aprenderá como funcionam as tags, como ocultar campos vazios, como serializar structs aninhadas e como não cometer erros. Vamos lá!
Fundamentos: pacote encoding/json
Na biblioteca padrão do Go, existe o poderoso pacote encoding/json. Suas principais ferramentas são as funções json.Marshal (para converter struct em JSON) e json.Unmarshal (para o processo inverso).
Vamos ver um exemplo básico. Temos uma struct de usuário:
package main
import ( "encoding/json" "fmt")
type User struct { Name string Age int Email string}
func main() { user := User{ Name: "Alexey", Age: 30, Email: "alex@example.com", }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Erro:", err) return }
fmt.Println(string(jsonData)) // Saída: {"Name":"Alexey","Age":30,"Email":"alex@example.com"}}Funciona, mas há um detalhe: as chaves no JSON correspondem aos nomes dos campos da struct (com letra maiúscula). Isso não segue os padrões JSON (geralmente usa-se camelCase ou snake_case).
Tags JSON: controle sobre nomes de chaves
Para controlar como os campos aparecerão no JSON, usamos tags de struct. São anotações especiais escritas após o tipo do campo entre crases.
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email"`}
// Agora a saída será:// {"name":"Alexey","age":30,"email":"alex@example.com"}As tags resolvem vários problemas:
- Alterar o nome do campo — deixando as chaves bonitas e legíveis
- Pular campo — com
json:"-"o campo é completamente excluído do JSON - Gerenciar campos vazios — a opção
omitemptyoculta o campo se ele contiver valor zero
Exemplo prático com omitempty
type User struct { Name string `json:"name"` Age int `json:"age,omitempty"` Email string `json:"email,omitempty"` IsAdmin bool `json:"is_admin,omitempty"`}
func main() { user := User{Name: "Maria"} jsonData, _ := json.Marshal(user) fmt.Println(string(jsonData)) // Saída: {"name":"Maria"} // Age, Email e IsAdmin foram omitidos por estarem vazios}Observe: omitempty funciona para valores zero — 0, false, string vazia, nil. Isso é muito útil para APIs onde não é necessário carregar campos extras.
Structs aninhadas e slices
Em projetos reais, os dados raramente são planos. Frequentemente você tem objetos aninhados ou arrays. O Go lida muito bem com isso — o pacote json processa recursivamente todos os campos.
type Address struct { City string `json:"city"` Street string `json:"street"` ZipCode string `json:"zip_code"`}
type Company struct { Name string `json:"name"` Address Address `json:"address"` Tags []string `json:"tags"`}
func main() { company := Company{