我正在尝试使用Retrofit和Jackson进行反序列化来调用API,但是我遇到了onFailure错误 No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator
。
原因:
此错误发生是因为Jackson库不知道如何创建您的模型,该模型没有空构造函数,并且模型包含一个带有参数的构造函数,但未对其参数进行注释@JsonProperty("field_name")
。如果您的类没有添加构造函数,默认情况下Java编译器会创建一个空构造函数。
解决方案:
向您的模型添加一个空构造函数或使用@JsonProperty("field_name")
对构造函数参数进行注释。
如果您使用的是Kotlin数据类,则还可以使用@JsonProperty("field_name")
进行注释,或者将jackson module kotlin注册到ObjectMapper
中。
您可以使用http://www.jsonschema2pojo.org/创建您的模型。
我在寻找以下错误而来到这里:
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
上述链接中最相关的部分:
“如果Jackson无法访问构造函数,则会引发此异常。当我们尝试反序列化JSON字符串时,会抛出JsonMappingException: No Suitable Constructor Found
。为了解决这个问题,我们只需添加一个默认构造函数:”
public Foo() {
super();
}
现在当我们反序列化时,该过程将正常工作。
@JsonCreator
或@ConstructorProperties({"prop1Name", "propr2Name"})
可以解决上述错误。 - Kirill@Data static class LoginResponse { private final String token,message; private final int status; }
但是这样可以:
@Data static class LoginResponse { private String token, message; private int status; }
- Vladtn如果你在一个 POJO 模型中使用 Lombok,请确保你有以下注解:
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
可能会有所不同,但请确保@Getter
,尤其是@NoArgsConstructor
。
@NoArgsConstructor
可以解决我的问题。我的完整注释如下:@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@JsonInclude(Include.NON_DEFAULT)
- davide@Data
相当于 @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode
。因此可能只需要 @NoArgsConstructor
。 - 54l3d@Data
注释中指定另一个构造函数注释,则不会包括@RequiredArgsConstructor
。 - payne@NoArgsConstructor
和@AllArgsConstructor
都是必需的。谢谢! - Fatmajk你需要使用jackson-module-kotlin
来反序列化数据类。详情请参见这里。
如果尝试将一些值反序列化为数据类时没有启用该模块,或者即使启用了该模块但使用的ObjectMapper
没有注册KotlinModule
,则上面的错误消息是Jackson提供的。例如,看下面的代码:
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)
如果您更改上面的代码,并将ObjectMapper
替换为jacksonObjectMapper
(它只是返回一个已注册KotlinModule
的普通ObjectMapper
),它可以工作。即:
val deserializedValue = jacksonObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)
对于Android方面,我不确定,但看起来您需要让系统使用jacksonObjectMapper
来进行反序列化。
mapper.registerModule(KotlinModule())
的位置。 - Jayson Minard我正在使用Quarkus、Jackson和Lombok。因此,我通过在模型类上添加@Jacksonized
属性来解决了这个问题。
所以所有的属性都是:
@Jacksonized //missing
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ...
我遇到了类似的问题(使用Jackson、lombok和gradle),并且有一个没有无参构造函数的POJO - 解决方法是添加
lombok.anyConstructor.addConstructorProperties=true
到 lombok.config 文件中
我知道这是一个旧的帖子,但对于使用 Retrofit 的任何人来说,这可能很有用。
如果您正在使用 Retrofit + Jackson + Kotlin + Data classes,则需要:
implement group: 'com.fasterxml.jackson.module',name:'jackson-module-kotlin',version:'2.7.1-2'
添加到依赖项中,以便 Jackson 可以将其反序列化为数据类 val jsonMapper = com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()
val retrofit = Retrofit.Builder()
...
.addConverterFactory(JacksonConverterFactory.create(jsonMapper))
.build()
注意:如果没有使用Retrofit,@Jayson Minard提供了一种更通用的方法。
我正在使用Lombok。 我之所以出现错误,是因为我没有在我的模型类中放置@NoArgsConstructor
。
我通过添加一个无参构造函数解决了这个问题。如果您使用Lombok,您只需要添加@NoArgsConstructor
注释:
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class User {
private Long userId;
private String shortName;
}
@Builder
时,使用 @Jacksonized
可选(可能用于其他目的),但不是 Jackson-izing 本身所必需的。 - cellepo
@JsonCreator
注释进行反序列化。 - Krzysztof Tomaszewski