Serialização em Go: JSON Primeiro, Formatos Sob Demanda
Serviços Go passam a maior parte do tempo de serialização transformando structs em JSON e vice-versa.
Busque em todas as páginas da documentação
Serviços Go passam a maior parte do tempo de serialização transformando structs em JSON e vice-versa.
A biblioteca padrão envia codificadores criados especificamente para formatos comuns e um pequeno conjunto de interfaces permite que você substitua o comportamento quando os padrões não são adequados.
Noções Básicas de Serialização coleta trechos executáveis; páginas irmãs cobrem marshaling customizado, formatos alternativos, tags de struct, evolução de esquemas, bibliotecas de desempenho, validação e convenções de equipe.
encoding/json é a escolha padrão; outros pacotes em encoding/* e codecs de terceiros preenchem necessidades especializadas.Serialização responde a uma pergunta: como você transforma uma struct User em bytes que outro programa pode ler?
A resposta de Go começa com codificadores baseados em reflexão na biblioteca padrão.
json.Marshal percorre os campos exportados da struct, lê as tags json e emite JSON UTF-8.
json.Unmarshal faz o inverso, alocando structs e slices aninhados conforme necessário.
O padrão se repete em todos os formatos:
| Pacote | Uso Típico | Formato de Comunicação |
|---|---|---|
encoding/json | APIs REST, arquivos de configuração | JSON em Texto |
encoding/xml | SOAP, RSS, legado empresarial | XML em Texto |
encoding/gob | RPC Go-para-Go ou caches | Binário, específico para Go |
google.golang.org/protobuf | gRPC, contratos entre linguagens | Protobuf binário |
A maioria dos caminhos de código Go em produção toca em JSON primeiro.
Manipuladores em chi, gin e echo vinculam corpos JSON através de encoding/json ou wrappers finos.
google.golang.org/grpc usa protobuf, não JSON, na comunicação (gateways podem transcodificar para JSON).
Tags de struct são a principal superfície de configuração:
type Profile struct {
ID string `json:"id"`
Email string `json:"email,omitempty"`
Internal string `json:"-"`
CreatedAt time.Time `json:"created_at"`
}omitempty remove valores zero da saída.- oculta um campo do JSON inteiramente.Quando as tags não são suficientes, implemente json.Marshaler e json.Unmarshaler:
func (t TimeOnly) MarshalJSON() ([]byte, error) {
return json.Marshal(t.Format("15:04:05"))
}O codificador verifica essas interfaces antes de usar as regras padrão.
APIs de streaming (json.Encoder, json.Decoder) são adequadas para corpos de resposta HTTP e entradas grandes sem carregar tudo na memória.
Opções do decodificador são importantes na produção:
Decoder.DisallowUnknownFields() rejeita chaves inesperadas (APIs estritas).UseNumber() mantém inteiros grandes como json.Number em vez de float64.A validação pertence a uma etapa separada.
go-playground/validator lê as tags validate após o JSON ser carregado em uma struct.
A serialização não impõe regras de negócio; ela apenas traduz formatos.
A evolução de esquemas é um problema de contrato.
Servidores devem adicionar campos sem quebrar clientes antigos; clientes devem ignorar chaves desconhecidas.
Protobuf formaliza números de campo; JSON depende de disciplina e testes.
json.RawMessage adia a análise de blobs aninhados para que você possa decodificar payloads parciais de forma compatível com versões futuras.
O desempenho se torna relevante em QPS alto ou em trabalhos em lote grandes.
json-iterator e sonic (verifique as versões na compilação) espelham as APIs encoding/json com reflexão mais rápida ou caminhos JIT.
Riscos de migração incluem diferenças sutis de comportamento em omitempty, tratamento de float64 e ordenação de MarshalJSON.
| Abordagem | Força | Fraqueza | Melhor Ajuste |
|---|---|---|---|
encoding/json | Estável, sem dependências | Mais lento em payloads enormes | APIs HTTP públicas |
| Protobuf + gRPC | Esquema binário compacto e versionado | Requer codegen e ferramentas | Microsserviços internos |
encoding/gob | Binário simples nativo Go | Não é multiplataforma | Caches locais de processo |
encoding/xml | Interoperabilidade empresarial | Verboso, frágil | Feeds legados |
MarshalJSON customizado | Controle total | Fácil de errar | Formatos de data, enums, redação |
Limites de tamanho pertencem à camada HTTP (http.MaxBytesReader) e à política da aplicação, não dentro de json.Marshal.
golangci-lint pode sinalizar tags de struct e tags JSON que se desviam dos nomes de campo quando as equipes habilitam linters de verificação de tags.
"", 0, false, ponteiros nil, slices vazios e tempos zero.json, db e validate lado a lado.JSON é legível por humanos, depurável com curl e suportado por todas as pilhas de clientes.
O codificador da biblioteca padrão é bom o suficiente para a maioria dos orçamentos de latência de API.
Use protobuf para serviços gRPC internos que precisam de cargas úteis binárias compactas e tipos multiplataforma gerados.
Mantenha JSON na borda para navegadores e REST público.
Implemente ambos quando o tipo faz um ciclo completo através de APIs.
Implementações unilaterais confundem leitores e quebram testes de simetria.
gin usa ShouldBindJSON; echo usa Bind; chi combina com json.NewDecoder(r.Body).
Todos, em última instância, dependem de encoding/json ou decodificadores compatíveis.
Use gopkg.in/yaml.v3 ou github.com/pelletier/go-toml/v2 para arquivos de configuração.
Mantenha APIs HTTP em JSON, a menos que os clientes exijam o contrário.
Não com os codificadores baseados em reflexão da biblioteca padrão.
Use marshalers customizados ou exporte campos destinados a formatos de comunicação.
Use json:"-", MarshalJSON customizado ou um DTO de log dedicado sem campos sensíveis.
Nunca confie em omitempty para senhas.
Principalmente sim, mas os limites de reflexão se aplicam em placas pequenas.
Verifique seu alvo com a nota de rodapé da pilha na hora da compilação.
Escolha uma convenção por superfície de API e codifique-a em tags de struct.
Documente a escolha em seu OpenAPI ou README.
Envolva r.Body com http.MaxBytesReader antes de decodificar.
Rejeite cargas úteis excessivamente grandes antes que Unmarshal aloque slices grandes.
Versões da Pilha: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026