杰克逊未能反序列化简单 JSON

Jackson failing to deserialize simple JSON

我正在使用 Lombok,@Annotations 为我创建了 getter、setter 和构造函数。我有许多其他的 类 杰克逊很容易反序列化。这是我要反序列化的对象:

@Value
@Builder
public class RecipeListRemoveDTO {
    int recipeListId;
}

在以下控制器方法中使用:

@DeleteMapping(path="/deleteRecipeListFromUser")
public @ResponseBody String deleteRecipeListFromUser(@RequestBody RecipeListRemoveDTO recipeListRemoveDTO) {
    return recipeListService.removeRecipeListFromUser(recipeListRemoveDTO);
}

我发送的JSON:

{
    "recipeListId": 2
}

但我收到错误消息:

"message": "JSON parse error: Cannot construct instance of com.prepchef.backend.models.dto.RecipeListRemoveDTO (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.prepchef.backend.models.dto.RecipeListRemoveDTO (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (PushbackInputStream); line: 2, column: 5]"

有人知道为什么会这样吗?

当您使用 Lomboks @Value annotation that's why you're getting the exception in your code. Instead you should use @Data 注释时,不会生成设置器。

这不起作用的原因是当您使用 @Value in conjunction with @Builder 时,没有生成 public 构造函数:

Also, any explicit constructor, no matter the arguments list, implies lombok will not generate a constructor. If you do want lombok to generate the all-args constructor, add @AllArgsConstructor to the class.

applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class

因此,总而言之,如果您希望保持 @Value 提供的不变性,在这种情况下您还需要添加 @AllArgsConstructor.

@Value
@Builder
@JsonDeserializer(builder = RecipeListRemoveDTO.RecipeListRemoveDTOBuilder.class)
public final class RecipeListRemoveDTO {
    int recipeListId;
    
    @JsonPOJOBuilder(withPrefix = "")
    public static final class RecipeListRemoveDTOBuilder {}
}

Jackson 不知道它应该使用 Lombok 生成的构建器。 可能最简单的解决方案是用 Lombok's @Jacksonized annotation 注释你的 class (自 Lombok 以来可用 1.18.14).

@Value
@Builder
@Jacksonized
public class RecipeListRemoveDTO {
    int recipeListId;
}

在幕后 @Jacksonized 注释导致 Lombok 做以下事情(这样你就不需要做这些 手动):

  • 它增加了@JsonDeserialize(builder=RecipeListRemoveDTO.RecipeListRemoveDTOBuilder.class) 到您的 class,以便 Jackson 知道它应该使用 反序列化的构建器。
  • 它将 @JsonPOJOBuilder(withPrefix="") 添加到构建器 class, 这样 Jackson 就知道构建器方法有一个名字 不是以 with.
  • 开头