No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator
Asked Answered
W

35

344

I am trying to consume an API using Retrofit and Jackson to deserialize. I am getting the onFailure error No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.

Wheaten answered 7/11, 2018 at 14:29 Comment(2)
You appear to not be using the Jackson Module for Kotlin, which works with data classes that have no default constructor as yours does not. Check out that module and see if you have any problems after.Finely
The reason for this is that Jackson (JSON deserialization library used by Spring WebClient) tries to deserialize into a class that has a non-default constructor only and in this case it cannot know which parameters to use for JSON attributes. This is only possible with debugging symbols present and some extra Jackson module (see other answers below). The normal way for Jackson in this case is to use @JsonCreator annotation on this non-default construtor in the class to deserialize.Padre
D
337

Reason: This error occurs because Jackson Library doesn't know how to create your model which doesn't have an empty constructor and the model contains a constructor with parameters that didn't annotate its parameters with @JsonProperty("field_name"). By default Java compiler creates an empty constructor if you didn't add a constructor to your class.

Solution: Add an empty constructor to your model or annotate constructor parameters with @JsonProperty("field_name")

If you use a Kotlin data class then also can annotate with @JsonProperty("field_name") or register jackson module kotlin to ObjectMapper.

You can create your models using http://www.jsonschema2pojo.org/.

Daw answered 7/11, 2018 at 15:34 Comment(11)
The reason this works is because they aren't data classes.Cornela
This is the solution. But which way is better? Creating a empy constructor in general or adding the JSON property?Prunella
@Maximus I think there is no difference in performance( if you mean better in performance). Creating an empty constructor is easier than adding annotation on each parameter.Daw
What if I can't modify the class I'm trying to deserialize? Is there any way to make this work? Is a custom deserializer the only option?Celestyn
What if I cannot edit the class? For example, I want to deserialize spring's Pair. Can I create a custom deserialization method outside of the Pair class?Embus
I was added both the empty constructor and/or jsonproperty annnotation. But didnt work. The interesting think is works with debug variant but dont work with release variantMcreynolds
I have found the error, maybe it will may minifed option or proguardMcreynolds
This solution worked. Also totally agree with you @Daw as I had no concern regarding performance.Ecumenicism
Thank you, using jacksonObjectMapper() fixed the issueXanthe
Had this issue on a Kotlin project, where, using a field named 'name' in a data class was also failing, I annotated the field with @JsonProperty("name"), which resolved it.Viewer
It did not work for me.Sherlocke
T
116

I got here searching for this error:

No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator

Nothing to do with Retrofit but if you are using Jackson this error got solved by adding a default constructor to the class throwing the error. More here: https://www.baeldung.com/jackson-exception

Most relevant bits from the link above:

"This exception is thrown if Jackson can't access the constructor. When we try to deserialize a JSON String, JsonMappingException: No Suitable Constructor Found is thrown. To solve this problem, we just add a default constructor:

    public Foo() {
        super();
    }

Now when we deserialize, the process will work just fine."

Timaru answered 7/7, 2019 at 16:22 Comment(3)
If you want your object to be immutable, you would not want to create a default constructor. Adding @JsonCreator or @ConstructorProperties({"prop1Name", "propr2Name"}) on constructor solves the error above.Methadone
If you are using Lobok and @Data, make sure your fields are not final otherwise empty constructor is not possible. So this doesn't work: @Data static class LoginResponse { private final String token, message; private final int status; } But this works: @Data static class LoginResponse { private String token, message; private int status; }Petey
Can you please add some brief details from this article? As it is it is technically a link-only answer but judging by the score this has clearly helped people. I don't want to see this get deleted over something so petty.Kurr
J
115

If you're using Lombok on a POJO model, make sure you have these annotations:

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor

It could vary, but make sure @Getter and especially @NoArgsConstructor.

Juggernaut answered 10/12, 2019 at 21:35 Comment(8)
@NoArgsConstructor was what solved my situation. My full anotations are @Data @AllArgsConstructor @NoArgsConstructor @Entity @JsonInclude(Include.NON_DEFAULT)Goins
@Data is equivalent to @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode So may be only @NoArgsConstructor is neededKetchum
@Ketchum @Data will not include @RequiredArgsConstructor if you specify another constructor annotation along with it.Rachellerachis
Just wanted to point that you saved my day :), I was missing the @NoArgsConstructor annotation all this time.Mercy
Both @NoArgsConstructor and @AllArgsConstructor were needed in my case. Thanks!Peipeiffer
The @NoArgsConstructor and @AllArgsConstructor helped to resolve this.Pinhead
I think when using @Builder, if @NoArgsConstructer is also used, then that is when @AllArgsConstructor must also be used. If no @Builder, then no @AllArgsConstructor needed (just @NoArgsConstructor).Junoesque
But I think just additionally using @Jacksonized instead, is the simplest :)Junoesque
R
80

You need to use jackson-module-kotlin to deserialize to data classes. See here for details.

The error message above is what Jackson gives you if you try to deserialize some value into a data class when that module isn't enabled or, even if it is, when the ObjectMapper it uses doesn't have the KotlinModule registered. For example, take this code:

data class TestDataClass (val foo: String)

val jsonString = """{ "foo": "bar" }"""
val deserializedValue = ObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)

This will fail with the following error:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `test.SerializationTests$TestDataClass` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)

If you change the code above and replace ObjectMapper with jacksonObjectMapper (which simply returns a normal ObjectMapper with the KotlinModule registered), it works. i.e.

val deserializedValue = jacksonObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)

I'm not sure about the Android side of things, but it looks like you'll need to get the system to use the jacksonObjectMapper to do the deserialization.

Ratib answered 7/11, 2018 at 14:34 Comment(8)
Have updated the answer with more info. I wonder if, although you have the module registered, the code which is doing the deserialization isn't explicitly using the jacksongObjectMapper? I'm just assuming it is related to this, because the error message you're getting is exactly what Jackson gives you when that object mapper isn't used.Ratib
Can I pass you the repository for you to take a look?Hydrazine
Go for it. Though I've never done any Android stuff so don't get your hopes up :-) I just answered this because I happened to come across exactly this problem the other day in some server-side Kotlin code.Ratib
The issue is definitely related to not using this module and using a data class. So, you need to register the module on the object mapper that is being used by the system. Find in your frameworks that you are using where you can modify the configuration of the object mapper to call mapper.registerModule(KotlinModule()) @joseFinely
José and Jayson writing about json :-DGuppy
Does this apply to non-kotlin, i.e. Java 8 applications too?Orchid
@JanacMeena, the solution in this answer is specific to Kotlin, but the error itself can potentially occur when deserializing to Java classes, if they are set up in some particular way (e.g. maybe only having a private constructor, or something like that, I haven't tried so not sure).Ratib
I am using Quarkus, with Kotlin, and rest api endpoint body using data class object. Adding the jackson-module-kotlin solved the issue.Didier
E
20

I am using Quarkus, Jackson and Lombok. So I solved this issue by adding @Jacksonized attribute on model class. So all attributes are:

@Jacksonized //missing
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ...
Extender answered 2/11, 2021 at 8:53 Comment(1)
@Jacksonized always works with @Builder(Lambok) so add both of those to work. in my case my request body was having only on request entity named iBan. so when i tried to retrive data from request it was calling noargs constructor... in result i was unable to fetch payload data...Homogenesis
L
17

I had a similar issue (using Jackson, lombok, gradle) and a POJO without no args constructor - the solution was to add

lombok.anyConstructor.addConstructorProperties=true

to the lombok.config file

Linker answered 18/2, 2020 at 14:19 Comment(1)
This seems best if you're working with @Value...no extra annotations just to make your immutable classes deserializable.Recto
D
14

I know this is an old post, but for anyone using Retrofit, this can be useful useful.

If you are using Retrofit + Jackson + Kotlin + Data classes, you need:

  1. add implement group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.7.1-2' to your dependencies, so that Jackson can de-serialize into Data classes
  2. When building retrofit, pass the Kotlin Jackson Mapper, so that Retrofit uses the correct mapper, ex:
    val jsonMapper = com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()

    val retrofit = Retrofit.Builder()
          ...
          .addConverterFactory(JacksonConverterFactory.create(jsonMapper))
          .build()

Note: If Retrofit is not being used, @Jayson Minard has a more general approach answer.

Disini answered 12/3, 2019 at 18:52 Comment(2)
great! i think retrofit was using other instance of jacksonUveitis
I wish i could give you some rep points because you saved me in the last minute of extra time !! ThanksPunkah
L
11

I'm using Lombok. I got the error because I did not put @NoArgsConstructor in my model class.

Leet answered 6/8, 2022 at 13:28 Comment(0)
K
10

I solved this issue by adding a no argument constractor. If you are using Lombok, you only need to add @NoArgsConstructor annotation:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class User {
    private Long userId;
    private String shortName;
}
Kilbride answered 14/8, 2020 at 13:23 Comment(0)
O
10

If you use lombok you can use @Jacksonized annotation.

You don't need setters - this annotation works fine with @Value.

You don't need @NoArgsConstructor - you can use @Builder or just @RequiredArgsConstructor.

Ovum answered 19/1, 2023 at 17:33 Comment(3)
And I think the strict minimum when using @Builder, is for just @Jacksonized additionally (no others, like @Value, are strictly necessary).Junoesque
@Junoesque could you please paraphrase your message?Ovum
When using @Jacksonized with @Builder, @Value is optional (maybe for other purposes) but not necessary for the Jackson-izing itself.Junoesque
E
6

I'm using rescu with Kotlin and resolved it by using @ConstructorProperties

    data class MyResponse @ConstructorProperties("message", "count") constructor(
        val message: String,
        val count: Int
    )

Jackson uses @ConstructorProperties. This should fix Lombok @Data as well.

Exterior answered 4/12, 2019 at 19:58 Comment(1)
This is the only solution that works for me in a aws lambda + kotlin situation.Arrio
O
6

As the error mentioned the class does not have a default constructor.

Adding @NoArgsConstructor to the entity class should fix it.

Oaten answered 3/3, 2020 at 11:6 Comment(0)
K
6

Just need to add @NoArgsConstructor and it works.

Kenn answered 9/4, 2021 at 9:4 Comment(0)
D
4

Extending Yoni Gibbs's answer, if you are in an android project using retrofit and configure serialization with Jackson you can do these things in order to deserialization works as expected with kotlin's data class.

In your build gradle import:

implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.11.+"

Then, your implementation of retrofit:

val serverURL = "http://localhost:8080/api/v1"

val objectMapper = ObjectMapper()
objectMapper.registerModule(KotlinModule())
//Only if you are using Java 8's Time API too, require jackson-datatype-jsr310
objectMapper.registerModule(JavaTimeModule())

Retrofit.Builder()
    .baseUrl(serverURL)
    .client(
        OkHttpClient.Builder()
           .readTimeout(1, TimeUnit.MINUTES)//No mandatory
            .connectTimeout(1, TimeUnit.MINUTES)//No mandatory
            .addInterceptor(UnauthorizedHandler())//No mandatory
            .build())
    .addConverterFactory(
                JacksonConverterFactory.create(objectMapper)
            )
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

Data class:

@JsonIgnoreProperties(ignoreUnknown = true)
data class Task(val id: Int,
                val name: String,
                @JsonSerialize(using = LocalDateTimeSerializer::class)
                @JsonDeserialize(using = LocalDateTimeDeserializer::class)
                val specificDate: LocalDateTime?,
                var completed: Boolean,
                val archived: Boolean,
                val taskListId: UUID?
Discombobulate answered 10/5, 2020 at 21:27 Comment(1)
I am using Spring + Kotlin for Backend, and I resolved this problem with the KotlinModule(), thanks.Bracteole
M
4

Bek's answer is correct.

But in-case someone is trying to use immutable class in restcontroller i.e they are using lombok's @value then you need to add lombok.anyConstructor.addConstructorProperties=true

You can create a file named lombok.config in the same location where the root pom.xml is present and add this line into the file

https://mcmap.net/q/94303/-using-lombok-in-immutable-request-class

Muezzin answered 10/7, 2021 at 18:3 Comment(0)
J
4

I got the same error and after I added a constructor without parameters and then the problem was solved.

enter image description here

Journalistic answered 7/10, 2021 at 4:11 Comment(0)
B
4

For classes where we don't have a default construct, example when working with immutable objects, Jackson by default will not be able to deserialize JSON to the object. We can resolve this using some annotations like @JsonCreator which can help Jackson to know how to deserialize a given JSON.

A sample code will look like:

package com.test.hello;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Payment {

    private final Card card;

    private final Amount amount;

    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
    public Payment(@JsonProperty("card") Card card, @JsonProperty("amount") Amount amount) {
       this.card = card;
       this.amount = amount;
    }

    public Card getCard() {
       return card;
    }

    public Amount getAmount() {
        return amount;
    }
}
Broadus answered 10/5, 2022 at 15:14 Comment(0)
B
3

I had this issue and i fixed with the code below.

@Configuration
open class JacksonMapper {

    @Bean
    open fun mapper(): ObjectMapper {
        val mapper = ObjectMapper()
        ...

        mapper.registerModule(KotlinModule())
        return mapper
    }
}
Bobby answered 11/10, 2020 at 19:25 Comment(1)
KotlinModule() is now deprecated so use this: val mapper = ObjectMapper().registerModule(KotlinModule.Builder().build())Malayopolynesian
S
3

Be carefull with Lombok, expecially with @Builder.

what fixed the issue for me was :

   @JsonDeserialize(builder = X.XBuilder.class)
       class X{
          @JsonPOJOBuilder(withPrefix = "")
          public static class XBuilder{

          }
}

I hope it will make your life easier

Shandashandee answered 26/10, 2021 at 23:22 Comment(0)
S
2

by adding @NoArgsConstructor , it will fix the issue. Because compiler will add the default constructor if we have not provided any constructor, but if we have added any parameterized constructor and missed to add NoArgsConstructor we will get this exception. We should compulsorily add the default Constructor.

Subterfuge answered 11/5, 2022 at 7:50 Comment(0)
B
1

Just want to point out that this answer provides a better explanation.
Basically you can either have @Getter and @NoArgConstructor together
or let Lombok regenerates @ConstructorProperties using lombok.config file,
or compile your java project with -parameters flags,
or let Jackson use Lombok's @Builder

Bicuspid answered 22/8, 2020 at 19:18 Comment(0)
S
1

If you are using LOMBOK. Create a file lombok.config if you don't have one and add this line.

lombok.anyconstructor.addconstructorproperties=true
Sassafras answered 11/11, 2020 at 13:3 Comment(0)
R
1

Add Constructor in class OR if you are using pojo add @NoArgsConstructor @AllArgsConstructor

Also include JsonProperty - @JsonProperty("name") private List<Employee> name;

Reel answered 27/4, 2021 at 6:28 Comment(0)
W
1

This was mentioned already but not fully explained. With Lombok 1.14 and later you can addlombok.anyConstructor.addConstructorProperties=true to the lombok.config file located at the root directory of your project. If you have this and your POJO annotated with lombok

   @Builder
   @Getter

It will work because under the hood Lombok annotates the Builder's constuctor with @java.beans.ConstructorProperties() like here: enter image description here

By having the @java.beans.ConstructorProperties({param1, param2 ...}) annotation each parameter of your buider's constructor will be exposed via its getter, i.e, getCar(), getBrand() etc. This information is enough for Jackson to serialize your POJO properly via the getters.

Watchmaker answered 2/2, 2024 at 17:15 Comment(0)
H
0

If you are using Unirest as the http library, using the GsonObjectMapper instead of the JacksonObjectMapper will also work.

<!-- https://mvnrepository.com/artifact/com.konghq/unirest-object-mappers-gson -->
<dependency>
    <groupId>com.konghq</groupId>
    <artifactId>unirest-object-mappers-gson</artifactId>
    <version>2.3.17</version>
</dependency>
Unirest.config().objectMapper = GsonObjectMapper()
Hospitalize answered 10/9, 2019 at 10:36 Comment(0)
S
0

When you are using Lombok builder you will get the above error.

 @JsonDeserialize(builder = StationResponse.StationResponseBuilder.class)
 public class StationResponse{
   //define required properties 
 }     

 @JsonIgnoreProperties(ignoreUnknown = true)
 @JsonPOJOBuilder(withPrefix = "")
 public static class StationResponseBuilder {}

Reference : https://projectlombok.org/features/Builder With Jackson

Synthesize answered 29/2, 2020 at 13:37 Comment(0)
T
0

I could resolve this problem in Kotlin with help of @JacksonProperty annotation. Usage example for above case would be:

import com.fasterxml.jackson.annotation.JsonProperty
...
data class Station(
     @JacksonProperty("repsol_id") val repsol_id: String,
     @JacksonProperty("name") val name: String,
...
Theophilus answered 30/3, 2020 at 6:1 Comment(0)
C
0

My cause of issue seems very uncommon to me, not sure if anybody else gets the error under same condition, I found the cause by diffing previous commits, here you go :

Via my build.gradle I was using these 2 compiler options, and commenting out this line fixed the issue

//compileJava.options.compilerArgs = ['-Xlint:unchecked','-Xlint:deprecation']
Cottony answered 4/11, 2020 at 23:31 Comment(0)
M
0

Encountered the same error in below Usecase.

I tried to hit the Rest(Put mapping) end point using sprint boot(2.0.0 Snapshot Version) without having default constructor in respective bean.

But with latest Spring Boot versions(2.4.1 Version) the same piece of code is working without error.

so the bean default constructor is no longer needed in latest version of Spring Boot

Middleaged answered 27/12, 2020 at 14:16 Comment(0)
B
0

I got the same error and the problem was that my model didn't implement Serializable, so check this as well, might help since this is also one of the reason.

Bricole answered 17/4, 2021 at 7:0 Comment(1)
Hard to believe. Actually Serializable marker interface is not used by Jackson deserializer. I often see people do not understand the reasons for adding Serializable marker interface, which is mainly some result of EJB times and some confusion introduced by Hibernate/JPA requirements on embedded keys (where Serializable is required).Padre
T
0

I also faced the exception in Kotlin. If you're still having problem after applying KotlinModule, you might (though not quite probably) have value class somewhere.

Trochal answered 10/3, 2022 at 18:51 Comment(2)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewAnisotropic
@AbhishekDutt clarified my answerTrochal
L
0

I'm adding my answer, because I myself, due to my inattention, encountered this error.

Accidentally introduced the wrong serializer through the import of a static object and for a long time could not understand what was the reason. Maybe this will help someone else.

// Wrong serializer via static object import
import static org.keycloak.util.JsonSerialization.mapper;

Be careful.

Libbi answered 20/4, 2022 at 13:47 Comment(0)
O
0

In my case the problem occurred only in the build type release and was due to the obscuring of some classes in the '\dto' folder which contains the stubs. To solve I added the following rules in the proguard-rules.pro file:

-keep public class com.your.app_package.dto.** { *; }

-keep @**annotation** class * {*;}

#Preserve JacksonXml (PUBLIC_ONLY crash fix)
-keepattributes *Annotation*,EnclosingMethod,Signature
-keepnames class com.fasterxml.jackson.** { *; }
-dontwarn com.fasterxml.jackson.databind.**
-keep class org.codehaus.** { *; }
-keepclassmembers public final enum com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility {
    public static final com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility *; }
Optative answered 1/8, 2022 at 16:16 Comment(0)
O
0

If you use Kotlin and value class like this:

value class SomeId(val value: String) {
    override fun toString(): String = value
}

Then it won't work, even if you're going to nest this class within other e.g.

data class MyClass(val someId: SomeId)

There's open ticket about this, but it has been opened in 2018, so probably it won't be fixed. Instead you'll have to use primitive type instead so in this case

data class MyClass(val someId: String)
Ostensible answered 31/1, 2024 at 15:22 Comment(0)
M
0

You can use @JsonProperty to resolve the issue in most case just like above answers,but when your object to deserialize is in another library which is imported by maven or gradle repository,you can't change the source code.In this case,you can use annotation like @JsonDeserialize(converter = GeoJsonPointConverter.class)

public class Person {
  //GeoJsonPoint is a mongoDB object that provided by springframework
  //GeoJsonPoint doesn't have default constructor.
  @JsonDeserialize(converter = GeoJsonPointConverter.class)
  private GeoJsonPoint point;
  // getter & setter & other codes
}

public class GeoJsonPointConverter extends 
  StdConverter<Map<String,Double>,GeoJsonPoint> {
    @Override
    public GeoJsonPoint convert(Map<String,Double> value) {
        double x = value.get("x");
        double y = value.get("y");
        return new GeoJsonPoint(x,y);
    }
}

Your income json string looks like:

{point:{x:112.551243,y:28.274283}}

I think this is a more flexible way to resolve this issue.

Merilee answered 23/4, 2024 at 5:49 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.