Suporte de Jackson para Kotlin
1. Visão geral
Neste tutorial, discutiremos o suporteJackson para Kotlin.
Exploraremos como serializar e desserializarObjects eCollections. Também usaremos as anotações@JsonPropertye@JsonInclude.
2. Configuração do Maven
Primeiro, precisamos adicionar a dependênciajackson-module-kotlin ao nossopom.xml:
com.fasterxml.jackson.module
jackson-module-kotlin
2.9.8
A versão mais recente dejackson-module-kotlin pode ser encontrada no Maven Central.
3. Object serialização
Vamos começar com a serialização de objetos.
Aqui temos uma classe de dadosMovie simples que usaremos em nossos exemplos:
data class Movie(
var name: String,
var studio: String,
var rating: Float? = 1f)
Para serializar e desserializar objetos,we’ll need to have an instance of ObjectMapper for Kotlin.
Podemos criar um usandojacksonObjectMapper():
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
val mapper = jacksonObjectMapper()
Ou podemos criar umObjectMappere registrarKotlinModule:
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
val mapper = ObjectMapper().registerModule(KotlinModule())
Agora que temos nosso mapeador, vamos usá-lo para serializar um objetoMovie simples.
Podemos serializar um objeto para uma string JSON usando o métodowriteValueAsString():
@Test
fun whenSerializeMovie_thenSuccess() {
val movie = Movie("Endgame", "Marvel", 9.2f)
val serialized = mapper.writeValueAsString(movie)
val json = """
{
"name":"Endgame",
"studio":"Marvel",
"rating":9.2
}"""
assertEquals(serialized, json)
}
4. Object desserialização
A seguir, usaremos nosso mapeador para desserializar uma String JSON para uma instânciaMovie.
Usaremos o métodoreadValue():
@Test
fun whenDeserializeMovie_thenSuccess() {
val json = """{"name":"Endgame","studio":"Marvel","rating":9.2}"""
val movie: Movie = mapper.readValue(json)
assertEquals(movie.name, "Endgame")
assertEquals(movie.studio, "Marvel")
assertEquals(movie.rating, 9.2f)
}
Observe que não precisamos fornecer o métodoTypeReference parareadValue(); precisamos apenas especificar o tipo de variável.
Também podemos especificar o tipo de classe de uma maneira diferente:
val movie = mapper.readValue(json)
Durante a desserialização, se um campo estiver faltando na StringJSON, o mapeador usará o valor padrão declarado em nossa classe para esse campo.
Aqui, falta o camporating em nossa string JSON, então o valor padrão1 foi usado:
@Test
fun whenDeserializeMovieWithMissingValue_thenUseDefaultValue() {
val json = """{"name":"Endgame","studio":"Marvel"}"""
val movie: Movie = mapper.readValue(json)
assertEquals(movie.name, "Endgame")
assertEquals(movie.studio, "Marvel")
assertEquals(movie.rating, 1f)
}
5. Trabalhando comMaps
A seguir, veremos como serializar e desserializarMaps usando Jackson.
Aqui, serializaremos umMap<Int, String> simples:
@Test
fun whenSerializeMap_thenSuccess() {
val map = mapOf(1 to "one", 2 to "two")
val serialized = mapper.writeValueAsString(map)
val json = """
{
"1":"one",
"2":"two"
}"""
assertEquals(serialized, json)
}
A seguir,when we deserialize the map, we need to make sure to specify the key and value types:
@Test
fun whenDeserializeMap_thenSuccess() {
val json = """{"1":"one","2":"two"}"""
val aMap: Map = mapper.readValue(json)
assertEquals(aMap[1], "one")
assertEquals(aMap[2], "two")
}
6. Trabalhando comCollections
Agora, veremos como serializar coleções em Kotlin.
Aqui temosList de filmes que queremos serializar em uma string JSON:
@Test
fun whenSerializeList_thenSuccess() {
val movie1 = Movie("Endgame", "Marvel", 9.2f)
val movie2 = Movie("Shazam", "Warner Bros", 7.6f)
val movieList = listOf(movie1, movie2)
val serialized = mapper.writeValueAsString(movieList)
val json = """
[
{
"name":"Endgame",
"studio":"Marvel",
"rating":9.2
},
{
"name":"Shazam",
"studio":"Warner Bros",
"rating":7.6
}
]"""
assertEquals(serialized, json)
}
Agora, quando desserializamos aList, precisamos fornecer o tipo de objetoMovie - assim como fizemos comMap:
@Test
fun whenDeserializeList_thenSuccess() {
val json = """[{"name":"Endgame","studio":"Marvel","rating":9.2},
{"name":"Shazam","studio":"Warner Bros","rating":7.6}]"""
val movieList: List = mapper.readValue(json)
val movie1 = Movie("Endgame", "Marvel", 9.2f)
val movie2 = Movie("Shazam", "Warner Bros", 7.6f)
assertTrue(movieList.contains(movie1))
assertTrue(movieList.contains(movie2))
}
7. Alterando um nome de campo
A seguir,we can change a field name during serialization and deserialization using @JsonProperty annotation.
Neste exemplo, vamos renomear o campoauthorName paraauthor para uma classe de dadosBook:
data class Book(
var title: String,
@JsonProperty("author") var authorName: String)
Agora, quando serializamos um objetoBook,author é usado em vez deauthorName:
@Test
fun whenSerializeBook_thenSuccess() {
val book = Book("Oliver Twist", "Charles Dickens")
val serialized = mapper.writeValueAsString(book)
val json = """
{
"title":"Oliver Twist",
"author":"Charles Dickens"
}"""
assertEquals(serialized, json)
}
O mesmo vale para a desserialização também:
@Test
fun whenDeserializeBook_thenSuccess() {
val json = """{"title":"Oliver Twist", "author":"Charles Dickens"}"""
val book: Book = mapper.readValue(json)
assertEquals(book.title, "Oliver Twist")
assertEquals(book.authorName, "Charles Dickens")
}
8. Excluindo campos vazios
Finalmente, discutiremos como excluir campos vazios da serialização.
Vamos adicionar um novo campo chamadogenres à classeBook. Este campo é inicializado comoemptyList() por padrão:
data class Book(
var title: String,
@JsonProperty("author") var authorName: String) {
var genres: List? = emptyList()
}
Todos os campos são incluídos por padrão na serialização - mesmo se foremnull ou vazios:
@Test
fun whenSerializeBook_thenSuccess() {
val book = Book("Oliver Twist", "Charles Dickens")
val serialized = mapper.writeValueAsString(book)
val json = """
{
"title":"Oliver Twist",
"author":"Charles Dickens",
"genres":[]
}"""
assertEquals(serialized, json)
}
Podemos excluir campos vazios de JSON usando a anotação@JsonInclude:
@JsonInclude(JsonInclude.Include.NON_EMPTY)
data class Book(
var title: String,
@JsonProperty("author") var authorName: String) {
var genres: List? = emptyList()
}
Isso excluirá campos que sãonull, umCollection vazio, umMaps vazio, uma matriz com comprimento zero e assim por diante:
@Test
fun givenJsonInclude_whenSerializeBook_thenEmptyFieldExcluded() {
val book = Book("Oliver Twist", "Charles Dickens")
val serialized = mapper.writeValueAsString(book)
val json = """
{
"title":"Oliver Twist",
"author":"Charles Dickens"
}"""
assertEquals(serialized, json)
}
9. Conclusão
Neste artigo, aprendemos como usar Jackson para serializar e desserializar objetos no Kotlin.
Também aprendemos como usar as anotações@JsonPropertye@JsonInclude.
E, como sempre, o código-fonte completo pode ser encontradoover on GitHub.