uniqueuser-programmer
uniqueuser-programmer

Reputation: 105

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?

Upvotes: 5

Views: 1270

Answers (4)

Thomas Fritsch
Thomas Fritsch

Reputation: 10127

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.

Upvotes: 3

Oleg Cherednik
Oleg Cherednik

Reputation: 18245

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

Upvotes: 0

kenny_k
kenny_k

Reputation: 3980

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.

Upvotes: 1

dope
dope

Reputation: 315

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.

Upvotes: 0

Related Questions