不存在创建者,像默认构造一样):不能从对象值反序列化(没有基于委托或属性的创建者

我正在尝试使用Retrofit和Jackson来反序列化一个API。我得到的onFailure错误No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator

395237 次浏览

你需要使用jackson-module-kotlin来反序列化到数据类。详见在这里

上面的错误消息是Jackson给你的,如果你试图反序列化一些值到一个数据类,而该模块没有启用,或者即使启用了,当它使用的ObjectMapper没有注册KotlinModule时。例如,下面的代码:

data class TestDataClass (val foo: String)


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

这将失败,并出现以下错误:

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)

如果你改变上面的代码并用jacksonObjectMapper替换ObjectMapper(它只是返回一个正常的ObjectMapper,并注册了KotlinModule),它就可以工作。即。

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

我不确定Android方面的事情,但看起来你需要让系统使用jacksonObjectMapper来进行反序列化。

发生此错误是因为jackson库不知道如何创建没有空构造函数的模型,并且该模型包含带有参数的构造函数,该构造函数没有使用@JsonProperty("field_name")注释其参数。默认情况下,如果你没有给你的类添加构造函数,java编译器会创建空构造函数。

<强>解决方案: 在你的模型中添加一个空构造函数,或者用@JsonProperty("field_name")

注释构造函数参数

如果你使用Kotlin数据类,那么也可以用@JsonProperty("field_name")进行注释或将杰克逊模块kotlin注册为ObjectMapper

你可以使用http://www.jsonschema2pojo.org/创建你的模型。

我知道这是一个老帖子,但对于任何使用Retrofit的人来说,这可能是非常有用的。

如果你正在使用Retrofit + Jackson + Kotlin + Data类,你需要:

  1. implement group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.7.1-2'添加到您的依赖项中,以便Jackson可以反序列化为Data类
  2. 当构建翻新时,传递Kotlin Jackson Mapper,以便翻新使用正确的映射器,例如:
    val jsonMapper = com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()


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

注意:如果没有使用Retrofit, @Jayson Minard有一个更一般的方法回答。

我在这里搜索这个错误:

No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator
与Retrofit无关,但如果您使用Jackson,则通过向抛出错误的类添加默认构造函数来解决此错误。 更多:https://www.baeldung.com/jackson-exception

如果你使用Unirest作为http库,使用GsonObjectMapper代替JacksonObjectMapper也可以。

<!-- 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()

我使用Kotlin的rescu,并通过使用@ConstructorProperties来解决它

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

Jackson使用@ConstructorProperties。这应该修复Lombok @Data以及。

如果你在POJO模型上使用Lombok,确保你有这些注释:

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor

它可以变化,但确保@Getter尤其是@NoArgsConstructor

我有一个类似的问题(使用Jackson, lombok, gradle)和一个没有args构造函数的POJO -解决方案是添加

lombok.anyConstructor.addConstructorProperties=true

lombok.config文件

当您使用Lombok builder时,您将得到上述错误。

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


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

参考:https://projectlombok.org/features/Builder与杰克逊

正如错误所提到的,该类没有默认构造函数。

@NoArgsConstructor添加到实体类中应该可以修复它。

我可以在Kotlin中的@JacksonProperty注释的帮助下解决这个问题。上述情况的用法示例如下:

import com.fasterxml.jackson.annotation.JsonProperty
...
data class Station(
@JacksonProperty("repsol_id") val repsol_id: String,
@JacksonProperty("name") val name: String,
...

扩展Yoni Gibbs的回答,如果你在一个android项目中使用改装和配置序列化与Jackson,你可以做这些事情,以便反序列化工作预期与kotlin的数据类。

在你的build gradle导入中:

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

然后,你的改造实施:

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()

数据类:

@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?

我通过添加一个无参数的构造函数解决了这个问题。如果你正在使用Lombok,你只需要添加@NoArgsConstructor注释:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class User {
private Long userId;
private String shortName;
}

只是想指出这个回答提供了更好的解释。
基本上你可以让@Getter@NoArgConstructor一起
或让Lombok使用lombok.config文件再生@ConstructorProperties
或者用-parameters标志编译你的java项目,
或者让Jackson使用Lombok的@Builder

我有这个问题,我修复了下面的代码。

@Configuration
open class JacksonMapper {


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


mapper.registerModule(KotlinModule())
return mapper
}
}

我的问题原因对我来说似乎很不寻常,不确定是否有人在相同的条件下得到错误,我通过不同之前的提交找到了原因,在这里:

通过我的构建。gradle我正在使用这2个编译器选项,并注释掉这一行固定的问题

//compileJava.options.compilerArgs = ['-Xlint:unchecked','-Xlint:deprecation']

如果您正在使用LOMBOK。 创建文件lombok。

.

.

.
lombok.anyconstructor.addconstructorproperties=true

在下面的用例中遇到相同的错误。

我尝试使用sprint boot(2.0.0快照版本)到达Rest(Put映射)端点,而在各自的bean中没有默认的构造函数。

但是在最新的Spring Boot版本(2.4.1版本)中,同一段代码可以正常工作。

所以bean的默认构造函数是最新版本Spring Boot中需要的不再

只需要添加@NoArgsConstructor就可以了。

我得到了同样的错误,问题是我的模型没有实现< >强可序列化的< / >强,所以检查这个,可能有帮助,因为这也是原因之一是

在类中添加构造函数 或 如果您正在使用pojo添加 @NoArgsConstructor @AllArgsConstructor < / p > 还包括JsonProperty - @JsonProperty("name") private List<Employee> name; < / p >

Bek的答案是正确的。

但如果有人试图在restcontroller中使用不可变类,即他们正在使用lombok的@value,那么你需要添加lombok.anyConstructor.addConstructorProperties=true

您可以在存在根pom.xml的同一位置创建一个名为lombok.config的文件,并将这一行添加到该文件中

https://stackoverflow.com/a/56022839/6700081 < a href = " https://stackoverflow.com/a/56022839/6700081 " > < / >

我得到了同样的错误,在我添加了不带参数的构造函数之后,问题就解决了。

enter image description here

使用Lombok时要小心,尤其是@Builder。

解决这个问题的方法是:

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


}
}

我希望它能让你的生活更轻松

我用的是夸克、杰克逊和龙目岛。所以我通过在模型类上添加@Jacksonized属性解决了这个问题。 所以所有属性都是:

@Jacksonized //missing
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ...

我在Kotlin中也遇到了例外。如果在应用KotlinModule之后仍然有问题,您可能(尽管不太可能)在某个地方有值类。

我加上我的答案,因为我自己,由于我的疏忽,遇到了这个错误。

导入静态对象时不小心引入了错误的序列化器,很长时间都不明白是什么原因。也许这能帮到别人。

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

小心些而已。

对于我们没有默认构造的类,例如当使用不可变对象时,Jackson默认情况下将不能将JSON反序列化为对象。 我们可以使用一些注释来解决这个问题,比如@JsonCreator,它可以帮助Jackson知道如何反序列化给定的JSON

示例代码如下所示:

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;
}
}

通过添加@NoArgsConstructor,它将修复这个问题。 因为如果我们没有提供任何构造函数,编译器将添加默认构造函数,但如果我们添加了任何参数化构造函数,并且错过添加NoArgsConstructor,我们将得到此异常。我们应该强制添加默认的构造函数

在我的案例中,问题只发生在构建类型发布中,这是由于包含存根的'\dto'文件夹中的一些类模糊造成的。 为了解决这个问题,我在proguard-rules中添加了以下规则。支持文件:< / p >
-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 *; }

我用龙目岛。我得到的错误,因为我没有把@NoArgsConstructor在我的模型类。