Gson — uma biblioteca do Google para serializar objetos Java para JSON e vice-versa, amplamente usada no desenvolvimento Android. Ela permite converter grafos complexos de objetos em strings JSON compactas sem escrever parsers manualmente. De acordo com Google Gson, 2024, a biblioteca tem mais de 23 mil estrelas no GitHub e continua sendo uma das soluções mais populares para trabalhar com JSON no ecossistema Java e Kotlin.
Principais Pontos
Gson é uma biblioteca Java desenvolvida pelo Google para converter objetos em representação JSON e vice-versa. Ela usa reflexão para analisar a estrutura das classes, permitindo trabalhar sem configuração prévia. Gson suporta objetos Java arbitrários, coleções, arrays, genéricos e classes aninhadas. A biblioteca não requer anotações para uso básico, mas as fornece para ajuste fino. A principal desvantagem da reflexão é a redução de desempenho durante a inicialização e a incapacidade de otimizar em tempo de compilação, o que é especialmente perceptível na inicialização a frio de um aplicativo Android ao desserializar centenas de modelos. Apesar disso, Gson continua sendo uma escolha confiável para a maioria dos projetos graças à sua estabilidade e documentação extensa.
Gson foi lançado pelo Google em 2008 e rapidamente se tornou o padrão de facto para JSON em aplicativos Android. Antes do surgimento do Moshi e kotlinx.serialization, Gson era a única escolha popular para projetos Kotlin. Facilidade de integração — adicionar uma única dependência ao build.gradle — e a ausência de anotações obrigatórias tornaram Gson popular entre desenvolvedores de todos os níveis.
// Adicionar Gson no build.gradle
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}
// Uso básico
data class User(
val id: Int,
val name: String,
val email: String
)
val gson = Gson()
val user = User(1, "John", "john@test.com")
val json = gson.toJson(user)
println(json) // {"id":1,"name":"John","email":"john@test.com"}
Além da serialização básica, Gson fornece GsonBuilder para configurar o comportamento: formatação de datas, desativação de escape HTML, formatação de chaves e instâncias personalizadas. GsonBuilder também permite registrar JsonSerializer e JsonDeserializer personalizados para tipos que a biblioteca não pode manipular automaticamente. A flexibilidade de configuração torna o GsonBuilder uma ferramenta indispensável e útil ao adaptar a biblioteca aos requisitos específicos do projeto no desenvolvimento Android moderno.
toJson converte um objeto Java em uma string JSON analisando seus campos através de reflexão. Por padrão, Gson inclui todos os campos, exceto transient e static. O método suporta qualquer tipo: primitivos, objetos, coleções e arrays. fromJson realiza a operação inversa, aceitando uma string JSON e a classe do objeto de destino, e retorna uma instância com campos preenchidos.
Durante a serialização, Gson percorre recursivamente todos os campos do objeto, incluindo os aninhados. Referências cíclicas levam a StackOverflowError, portanto devem ser excluídas usando a anotação @Expose ou um adaptador personalizado. Para coleções, Gson preserva os tipos de elementos, mas ao desserializar uma lista com genéricos, é necessário TypeToken para preservar informações de tipo.
// data class com objeto aninhado
data class Address(
val city: String,
val street: String
)
data class Employee(
val id: Int,
val name: String,
val address: Address
)
val gson = Gson()
val employee = Employee(1, "Alice",
Address("New York", "5th Ave"))
// Serialização para JSON
val json = gson.toJson(employee)
// Desserialização de JSON
val jsonString = """
{"id":2,"name":"Bob","address":{"city":"London","street":"Baker St"}}
"""
val parsed = gson.fromJson(jsonString, Employee::class.java)
Gson fornece um conjunto de anotações para gerenciar o processo de serialização. @SerializedName especifica o nome da chave JSON que difere do nome do campo. @Expose controla se um campo é incluído na serialização: Gson criado via GsonBuilder.excludeFieldsWithoutExposeAnnotation() processará apenas campos com @Expose. @Since e @Until controlam o versionamento de campos.
A anotação @SerializedName resolve o problema de incompatibilidade de nomes: o servidor pode usar snake_case enquanto o código usa camelCase. A anotação aceita um valor e alternativas opcionais para compatibilidade retroativa. @Expose permite ocultar campos sensíveis (senhas, tokens) da serialização marcando-os como @Expose(serialize = false). Além da inclusão e exclusão, @Expose pode ser combinado com GsonBuilder.excludeFieldsWithoutExposeAnnotation para criar uma lista branca de campos, o que ajuda a controlar a superfície de ataque ao serializar objetos com muitos campos.
// Modelo com anotações Gson
data class UserResponse(
@SerializedName("user_id")
val userId: Int,
@SerializedName("full_name",
alternate = [Alternative("name")])
val fullName: String,
@Expose(serialize = false)
val password: String
)
// Gson com filtragem @Expose
val gson = GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create()
val user = UserResponse(1, "John", "secret123")
println(gson.toJson(user))
// {"user_id":1,"full_name":"John"} — senha excluída
O problema dos genéricos em Java e Kotlin é o apagamento de tipo em tempo de compilação. Quando Gson desserializa List<User>, ele não sabe o tipo do elemento e retorna List<Map<String, Any>>. Para preservar informações de tipo, Gson fornece TypeToken — uma classe abstrata que captura o parâmetro de tipo através de uma classe anônima. Sem TypeToken, o desenvolvedor teria que converter manualmente cada elemento de Map para o tipo de destino, resultando em código pesado e perda de desempenho.
TypeToken resolve o problema de apagamento de tipo. O desenvolvedor cria uma subclasse anônima de TypeToken com o parâmetro de tipo necessário, e Gson usa as informações da assinatura da classe para desserialização correta. TypeToken também funciona com Map, Set e qualquer outro tipo parametrizado, incluindo genéricos aninhados. Em particular, para Map<String, List<User>>, é necessário um TypeToken com a assinatura completa do tipo aninhado, caso contrário Gson desserializa valores como List<Map<String, Any>> em vez de List<User>.
// TypeToken para desserialização de lista
data class Product(
val id: Int,
val title: String,
val price: Double
)
val jsonArray = """
[
{"id":1,"title":"Phone","price":599.0},
{"id":2,"title":"Laptop","price":1299.0}
]
"""
val gson = Gson()
val listType = object : TypeToken<List<Product>>() {}
val products: List<Product> =
gson.fromJson(jsonArray, listType.type)
// Desserializador personalizado
class LocalDateAdapter :
JsonDeserializer<LocalDate> {
override fun deserialize(
json: JsonElement,
typeOfT: java.lang.reflect.Type,
context: JsonDeserializationContext
): LocalDate {
return LocalDate.parse(json.asString)
}
}
Para lógica de serialização personalizada, Gson suporta as interfaces JsonSerializer e JsonDeserializer. Elas são registradas via GsonBuilder.registerTypeAdapter() e permitem manipular tipos que a biblioteca não pode serializar automaticamente: datas Java 8, Enums com valores não padrão ou classes de terceiros sem acesso ao código fonte. Ao implementar um adaptador, é importante monitorar o desempenho: chamar reflexão dentro de um adaptador personalizado anula as vantagens do controle manual, portanto chamadas diretas a métodos e campos são preferíveis. No ecossistema Gson, também existe o módulo gson-extras, que fornece adaptadores para tipos comuns como UUID, Optional e rodas de data Joda-Time.
GsonBuilder fornece dezenas de métodos para ajuste fino da serialização. setPrettyPrinting adiciona indentação e quebras de linha ao JSON de saída para legibilidade. disableHtmlEscaping desativa o escape de caracteres HTML em strings. setDateFormat especifica o formato de data, o que é crítico ao trabalhar com servidores que usam representações de tempo não padrão. setLenient ativa o modo de análise tolerante, que ignora certos erros de formatação JSON. addDeserializationExclusionStrategy permite excluir programaticamente campos da desserialização com base em estratégias personalizadas. Para depuração, setPrettyPrinting combinado com logging é útil — torna as respostas JSON legíveis nos logs e simplifica a busca por inconsistências.
Uma característica importante do GsonBuilder é o gerenciamento de versionamento de campos através das anotações @Since e @Until. O desenvolvedor especifica a versão do objeto via setVersion, e Gson inclui ou exclui automaticamente campos com base em sua anotação de versão. Isso é útil durante a evolução da API, quando o mesmo modelo é usado para diferentes versões do protocolo do servidor. GsonBuilder também suporta o registro de TypeAdapterFactory para manipulação global de tipos de família e complexMapKeySerialization para trabalho correto com chaves complexas de Map.
Perguntas Frequentes
Gson é uma biblioteca do Google para converter objetos Java para JSON e vice-versa. É amplamente usado em aplicativos Android para analisar respostas do servidor, serializar requisições e armazenar dados no armazenamento local.
Por padrão, Gson omite campos null durante a serialização. Para incluir valores null, use GsonBuilder.serializeNulls(). Durante a desserialização, campos ausentes no JSON permanecem null ou assumem o valor padrão do tipo.
Moshi não usa reflexão para classes Kotlin, o que proporciona maior desempenho e comportamento previsível. Moshi também lida corretamente com a segurança de null do Kotlin, enquanto Gson pode desserializar null em um campo não anulável, causando uma exceção.
@SerializedName vincula uma chave JSON a um campo de classe quando seus nomes não coincidem. Por exemplo, para o campo kotlinName e a chave JSON "kotlin_name", a anotação @SerializedName("kotlin_name") garante a conversão correta.
TypeToken é uma classe abstrata que captura o parâmetro de tipo através de uma classe anônima. É necessário para desserializar coleções e outros tipos parametrizados, porque devido ao apagamento de tipo, Gson não consegue recuperar o tipo do elemento em tempo de execução.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também