Question
How to Fix Jackson "No Creators, like default construct, exist" Error in Java Retrofit Deserialization
Question
I am consuming an API in a Java application using Retrofit and Jackson for JSON deserialization. During the request, Retrofit triggers onFailure with this Jackson error:
No Creators, like default construct, exist: cannot deserialize from Object value (no delegate- or property-based Creator)
Why does this happen, and how can I fix my model class so Jackson can deserialize the API response correctly?
Short Answer
By the end of this page, you will understand what Jackson means by a Creator, why Retrofit surfaces this error during deserialization, and how to fix your Java model classes using a no-argument constructor, @JsonCreator, and @JsonProperty when needed.
Concept
Jackson converts JSON into Java objects by creating an instance of your class and then filling in its fields or calling its constructor parameters.
That error means Jackson received a JSON object like this:
{
"id": 1,
"name": "Alice"
}
but it could not figure out how to create the Java object first.
In Jackson, a Creator is a way to build an object during deserialization. Common options are:
- a public no-argument constructor
- a constructor annotated with
@JsonCreator - constructor parameters annotated with
@JsonProperty - a builder pattern configured for Jackson
If your class only has a constructor with parameters and no default constructor, Jackson often cannot instantiate it automatically unless you explicitly tell it how.
This matters in real programming because API clients depend on reliable mapping between JSON responses and Java classes. If your models are not deserialization-friendly, network calls may succeed but object mapping will fail.
Mental Model
Think of Jackson as a delivery worker bringing JSON data to your Java class.
- The JSON is the package.
- Your Java class is the apartment.
- Jackson must first get inside the apartment before placing the items.
If the apartment has an unlocked front door, that is like a no-argument constructor.
If the apartment requires a special entry code, that is like a constructor with parameters. Jackson needs clear instructions about which values go where. Those instructions are provided with @JsonCreator and @JsonProperty.
Without a door or instructions, Jackson stands outside and throws the "No Creators" error.
Syntax and Examples
Basic fix: add a no-argument constructor
If your class uses mutable fields or setters, the simplest fix is often to add a default constructor.
public class User {
private int id;
private String name;
public User() {
// Default constructor required by Jackson
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Jackson can now:
- call
new User() - set
id - set
name
Alternative fix: use @JsonCreator
If you want immutable objects, use a constructor and tell Jackson how to map JSON fields.
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class User {
private final int id;
private final String name;
@JsonCreator
public User(
@JsonProperty("id") int id,
@JsonProperty("name") String name
) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
This tells Jackson exactly how to build the object from JSON.
Typical Retrofit API interface
public interface ApiService {
@GET("users/1")
Call<User> getUser();
}
If the response JSON matches the User class, Retrofit and Jackson can deserialize it successfully.
Step by Step Execution
Consider this JSON response:
{
"id": 10,
"name": "Maya"
}
And this Java class:
public class User {
private int id;
private String name;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
What Jackson does:
- Reads the JSON object.
- Sees that it needs a
Userobject. - Looks for a way to create
User. - Finds
public User(). - Creates a new
Userinstance. - Finds
idin JSON and callssetId(10). - Finds
namein JSON and callssetName("Maya"). - Returns the completed object.
Now consider this broken class:
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
What happens here:
- Jackson reads the JSON object.
- It needs a
Userinstance. - It does not find a no-argument constructor.
- It sees a parameterized constructor, but it does not know which JSON fields map to which parameters.
- It throws the "No Creators" error.
Fixing it with annotations:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class User {
private final int id;
private final String name;
@JsonCreator
public User(
@JsonProperty("id") int id,
@JsonProperty("name") String name
) {
this.id = id;
this.name = name;
}
}
Real World Use Cases
This issue appears often in API-driven Java applications.
Mobile or Android apps using Retrofit
A request succeeds, but parsing fails because the response model has only custom constructors.
Backend services consuming other APIs
A service calls an external API and maps the result into DTOs. If the DTOs are immutable but not annotated correctly, deserialization breaks.
JSON config loading
Applications often load JSON configuration into Java objects. Jackson still needs a valid way to create each object.
Data transfer objects in layered apps
Controllers, services, and clients often use DTO classes. These classes must be designed with serialization and deserialization in mind.
Real Codebase Usage
In real projects, developers usually choose one of these patterns:
1. Mutable DTOs with no-arg constructors
Common in simple apps and generated models.
public class ProductDto {
private String sku;
private double price;
public ProductDto() {}
public String getSku() { return sku; }
public void setSku(String sku) { this.sku = sku; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}
2. Immutable DTOs with @JsonCreator
Common when developers want safer objects.
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ProductDto {
private final String sku;
private final double price;
@JsonCreator
public ProductDto(
@JsonProperty("sku") String sku,
@JsonProperty("price") double price
) {
this.sku = sku;
this.price = price;
}
public String getSku() { return sku; }
public double getPrice() { return price; }
}
3. Validation after deserialization
Developers often deserialize first, then validate required fields.
if (user.getName() == null || user.getName().isBlank()) {
throw new IllegalArgumentException("Name is required");
}
4. Mapping API models to domain models
Large codebases often keep Retrofit/Jackson models separate from business objects.
User apiUser = response.body();
DomainUser domainUser = new DomainUser(apiUser.getId(), apiUser.getName());
This keeps serialization concerns out of core business logic.
Common Mistakes
1. Only defining a parameterized constructor
This is the most common cause.
Broken
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
Fix
- add a no-argument constructor, or
- annotate the constructor with
@JsonCreatorand@JsonProperty
2. Missing getters and setters for mutable classes
If Jackson relies on setters and they do not exist, field population may fail.
public class User {
private int id;
}
Safer version:
public class User {
private int id;
public User() {}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
3. JSON field names do not match Java property names
If the API returns full_name but your class uses fullName, mapping may fail unless configured.
import com.fasterxml.jackson.annotation.JsonProperty;
public class User {
@JsonProperty("full_name")
private String fullName;
public User() {}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
}
4. Using final fields without a creator constructor
final fields usually mean values must be set in the constructor. If Jackson cannot use that constructor, deserialization fails.
5. Assuming onFailure always means network failure
With Retrofit, converter errors may also appear in failure paths depending on setup. Always inspect the exception message and stack trace.
6. Nested classes not deserializable
If your response contains nested objects, every nested class must also be deserializable.
Comparisons
| Approach | How Jackson creates object | Best for | Pros | Cons |
|---|---|---|---|---|
| No-arg constructor + setters | Create empty object, then set fields | Simple DTOs | Easy to understand | Mutable objects |
@JsonCreator + @JsonProperty | Call constructor with JSON values | Immutable DTOs | Clear mapping, safer objects | More verbose |
| Public fields | Direct field access | Quick prototypes | Minimal code | Less encapsulation |
| Builder pattern | Use configured builder | Complex objects | Flexible for large models | More setup |
No-arg constructor vs @JsonCreator
- Use a no-arg constructor when you are okay with mutable objects.
- Use
@JsonCreatorwhen you want constructor-based deserialization and immutable fields.
Retrofit vs Jackson responsibility
| Tool | Responsibility |
|---|---|
| Retrofit | Makes HTTP requests and routes responses |
| Jackson | Converts JSON into Java objects |
Retrofit is usually not the root cause here. The problem is normally in the Jackson model mapping.
Cheat Sheet
// Option 1: mutable class
public class User {
private int id;
private String name;
public User() {}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
// Option 2: immutable class
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class User {
private final int id;
private final String name;
@JsonCreator
public User(@JsonProperty("id") int id,
@JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
public int getId() { return id; }
public String getName() { return name; }
}
Remember
- Jackson must know how to instantiate your class.
- A no-arg constructor is the simplest solution.
- If using constructor parameters, annotate them.
- JSON names must match Java property names, or use
@JsonProperty. - Nested response classes must also be deserializable.
- Inspect stack traces: parsing errors are not the same as connection errors.
FAQ
Why does Jackson say "No Creators"?
Jackson cannot find a valid way to create an instance of your class during deserialization.
Do I always need a default constructor?
No. You can also use a constructor annotated with @JsonCreator and parameter names annotated with @JsonProperty.
Why does this happen in Retrofit onFailure?
Retrofit uses Jackson to parse the response. If parsing fails, the call may end up in the failure path depending on your adapter and converter setup.
Can private fields still be deserialized?
Yes, often they can, especially with getters/setters or Jackson configuration. But the object still needs a valid creation method.
What if my JSON field names are different from my Java fields?
Use @JsonProperty("json_name") to map them correctly.
Does this error mean the API response is invalid?
Not always. The JSON may be perfectly valid, but your Java class may not be compatible with Jackson deserialization.
Should I use mutable or immutable DTOs?
Both are valid. Mutable DTOs are simpler for beginners. Immutable DTOs are safer and often preferred in larger codebases.
Mini Project
Description
Create a small Java model for an API response representing a book. The purpose is to practice building a Jackson-friendly class that Retrofit can deserialize without throwing the "No Creators" error.
Goal
Build a response model that correctly deserializes JSON for a book object using constructor-based mapping.
Requirements
- Create a
Bookclass withid,title, andauthorfields. - Make the fields immutable using
final. - Use Jackson annotations so the class can be deserialized from JSON.
- Add getter methods for each field.
- Test it against a JSON object with matching keys.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.