杰克逊不能用一个参数构造函数构造实例

Posted

技术标签:

【中文标题】杰克逊不能用一个参数构造函数构造实例【英文标题】:Jackson cannot construct instance with one parameter constructor 【发布时间】:2020-10-19 03:11:47 【问题描述】:

我正在使用 Spring Boot 创建一个 Web 应用程序。其中一个端点需要一个具有一个属性的 json 对象,即studentId。我像其他函数一样使用 DTO 来捕获有效负载。

@PostMapping("/courses/id/students")
public SuccessResponse<Void> addEnrolls(@PathVariable Long id, @RequestBody StudentIdPayload payload) throws HandledException 
    courseService.addEnrolls(id, payload.getStudentId());
    return success(HttpStatus.OK);

@Data
@AllArgsConstructor
public class StudentIdPayload 
    private Long studentId;

但是当我尝试使用 json body "studentId":1 发布端点时,出现以下错误:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.bimoadityar.univms.dto.input.StudentIdPayload` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)

如果我只使用值1 发布它会起作用。

如何让它与对象有效负载一起工作?

有趣的是,当我向StudentIdPayload 添加另一个属性(例如String placeholder)时,它按预期工作,尽管这个解决方案感觉很老套。

【问题讨论】:

找到了一个相关的问题***.com/questions/41243608/…,对应的问题github.com/FasterXML/jackson-databind/issues/1498 【参考方案1】:

默认情况下,反序列化需要无参数构造函数,所以添加@NoArgsConstructor:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentIdPayload 
    private Long studentId;

另见:

Annotations: using custom constructor

【讨论】:

考虑到数据注解中有RequiredArgsConstructor,而且我没有任何私有的最终属性,如果需要的话,我确信已经存在一个无参数的构造函数。 显式添加@AllArgsConstructor时,@Data中的@RequiredArgsConstructor无效。 这确实有效。我错了,对不起。但我真的很惊讶这解决了我的问题,考虑到我对所有其他端点使用相同的注释并且它工作得很好。那好吧。感谢您的解决方案。【参考方案2】:

考虑到https://github.com/FasterXML/jackson-databind/issues/1498,这似乎是预期的行为。

对于我的特殊情况,我很满意将@JsonCreator 添加到我的构造函数中。

@Data
@AllArgsConstructor(onConstructor = @__(@JsonCreator))
public class StudentIdPayload 
    private Long studentId;

【讨论】:

以上是关于杰克逊不能用一个参数构造函数构造实例的主要内容,如果未能解决你的问题,请参考以下文章

C# 静态构造函数

使用杰克逊的 JSON 反序列化:没有找到适合类型的构造函数 - 可以提供默认构造函数或注释构造函数 [重复]

构造函数

使用 COM 的参数化构造函数实例化类

将参数传递给基类构造函数

C#静态类,构造函数带参数