Kotlinis vaikeväärtuste lisamine võimaldab andmeobjekte muuta ning lisada välju koos piirangutega, et antud väli ei ole kunagi väärtustamata (null). Selline lahendus töötab väga hästi näiteks andmebaasist loetavate andmetega, kuna andmeobjektide loomise üle on täielik kontroll ning väärtustamata väljadel kasutataksegi koodis defineeritud vaikeväärtusi. Probleeme võib aga tekkida JSONi deserialiseerimisel. Kuna suure tõenäosusega kasutatakse selle jaoks mõne kolmanda osapoole teeki, siis puudub täielik kontroll protsessi üle. Selgus, et näiteks kasutades Jackson teeki, käitub deserialiseerimine veidikene ettearvamatult.
Oletame, et meil on selline andmeobjekti definitisoon
data class Andmed(val number: Int = 1)
Kui deserialiseerida JSONit, milles väli täielikult puudub ({}
), siis kasutatakse õigesti
vaikeväärtust ning väli number saab väärtuseks 1.
Oletame, aga et soovime deserialiseerida järgnevat JSONit
{
"number": null
}
Selgub, et deserialiseerimisel saadakse tulemuseks objekt, millel tegelikult on välja number väärtuseks 0.
Põhjus on selles, et Kotlin saab aru, et väärtus peab eksisteerima ja seega üritatakse null konverteerida primitiiviks, mis tähendab antud juhul väärtust 0. Muutes number välja defintsiooni selliselt, et väli võib sisaldada ka null väärtust ei lahenda probleemi, sest siis määrataksegi välja värtuseks lihtsalt null.
Lahenduseks on seadistada Jacksoni konverteerija järgnevalt
val mapper = ObjectMapper()
mapper.registerModule(
KotlinModule.Builder()
.configure(KotlinFeature.NullIsSameAsDefault, enabled = true)
.build()
)
Seejärel peab välja definitisoonis lubama siiksi ka tühja väärtust (Int?
), ning seejärel
on { "number": null }
deserialiseerimise järel väljal korrektselt Kotlinis defineeritud vaikeväärtus 1.