简体   繁体   中英

Jackson failing to deserialize simple JSON

I'm using Lombok, and the @Annotations create getters, setters, and constructors for me. I have many other classes which Jackson deserializes easily. Here is the object I'm trying to deserialize to:

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

Used within the following Controller method:

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

And the JSON I am sending:

{
    "recipeListId": 2
}

But I'm receiving the error:

"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]"

Does anyone know why this may be the case?

The reason this doesn't work is that when you use @Value in conjunction with @Builder , no public constructor is generated:

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.

and

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

So, in summary, if you wish to maintain the immutability provided by @Value , in this case you also need to add @AllArgsConstructor .

Jackson didn't know that it should use the Lombok-generated builder. Probably the easiest solution is to annotate your class also with Lombok's @Jacksonized annotation (available since Lombok 1.18.14).

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

Under the hood the @Jacksonized annotation causes Lombok to do the following things (so that you don't need to do these manually):

  • It adds @JsonDeserialize(builder=RecipeListRemoveDTO.RecipeListRemoveDTOBuilder.class) to your class, so that Jackson knows it should use the builder for deserialization.
  • It adds @JsonPOJOBuilder(withPrefix="") to the builder class, so that Jackson knows the buillder methods have a name not beginning by with .

Setters are not generated when you use Lomboks @Value annotation that's why you're getting the exception in your code. Instead you should use @Data annotation.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM