Introduction: Why does your Kotlin code suddenly "break" Jackson?
Have you ever written a beautiful, concise data class in Kotlin, added a couple of fields to it, started JSON deserialization via Jackson — and suddenly received a long, frightening error in your face? Sound familiar? If so, you are not alone. The error "No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator" is one of the most popular queries on Stack Overflow (thousands of views!) among developers transitioning from Java to Kotlin.
In this article, we will not just translate the error text. We will examine it "under a microscope": why it occurs, how to reproduce it, and, most importantly, how to get rid of it once and for all. You will get not only theory but also ready-made, proven solutions with Kotlin code. Let's go!
What does this error actually mean? In simple terms
Let's imagine that Jackson is a kind of "builder" who needs to assemble an object of your class from JSON bricks. To build a house, the builder needs a clear plan (constructor) or at least a set of ready-made walls (fields).
The error "No Creators, like default construct, exist" literally says: "Dear Jackson, I cannot create an object of this class because it has no default constructor (without parameters), and I don't know how to assemble it from the passed JSON fields!"
In Java, everything is simple: if you haven't written any constructors, the compiler kindly creates an empty default constructor. Jackson sees it and happily uses it. In Kotlin, however, if you define a data class with parameters in the constructor, a constructor without parameters is not created automatically. And Jackson, by default, looks for exactly that.
Reproducing the problem: Code that will crash with an error
Let's write a simple example that is guaranteed to cause this error. Imagine we have a user class:
import com.fasterxml.jackson.databind.ObjectMapperimport com.fasterxml.jackson.module.kotlin.readValueimport com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
// WARNING: This code will cause an error!data class User(val name: String, val age: Int)
fun main() { val mapper: ObjectMapper = jacksonObjectMapper() val json = """{"name": "Alexey", "age": 30}"""
// Attempting to deserialize JSON into a User object val user: User = mapper.readValue(json) println(user)}Run this code, and you will get the cherished exception:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `User` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"name": "Alexey", "age": 30}"; line: 1, column: 2]There it is, our "star" of Stack Overflow! Why did this happen? Because data class User(val name: String, val age: Int) does not have a constructor without parameters. All its fields are declared in the primary constructor, and they are mandatory (val). Jackson cannot create a User without knowing what values to pass to name and age, and without having hints in the form of setters.
3 ways to fix the error (from simple to correct)
The good news: there are several solutions. The choice depends on how much you want to control the process and what code you consider "clean".
Method 1: The simplest (but not for Kotlin purists)
Add a constructor without parameters manually. In Kotlin, this is done by specifying default values for all fields.
import com.fasterxml.jackson.databind.ObjectMapperimport com.fasterxml.jackson.module.kotlin.readValueimport com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
// Ye