Search code examples
javainheritancejacksonpolymorphismlombok

Jackson unable to recognise base class fields


I have the following Parent class

@Builder
@Jacksonized
@EqualsAndHashCode
@ToString
@Getter
@Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
@AllArgsConstructor
@NoArgsConstructor
@JsonTypeInfo(use = DEDUCTION)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Child.class, name = "Child")
}
)
public class Parent implements Serializable {

    private static final long serialVersionUID = 6223930820946596247L;

    @JsonProperty("recipient")
    protected Recipient recipient;
    
    .....
}

The Child class is as follows

@Builder(builderMethodName = "childRequestBuilder")
@Jacksonized
@EqualsAndHashCode
@ToString
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Child extends Parent implements Serializable {

    private static final long serialVersionUID = -2848064640409441165L;

    @JsonProperty("use_case")
    private String useCase;
}

I am trying to run the following test to check deserialisation. However, this throws the following error

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "recipient" (class a.b.Child$ChildRequestBuilder), not marked as ignorable (1 known properties: "use_case"]) at [Source: (String)"{"recipient":{"endpoint_details":{"someToken":"someToken","someDevice":"someDevice","someApp":"someApp"}}}"; line: 1, column: 129] (through reference chain: a.b.Child$ChildRequestBuilder["recipient"])

@Test
    public void testChildDeserialization() throws JsonProcessingException {
        SomeEndPoint endPoint = SomeEndpoint.builder().someToken("someToken").someDevice("someDevice").someApp("someApp").build();
        Recipient recipient = Recipient.builder().endpointDetails(endPoint).build();
        Child child = Child.childRequestBuilder().build();
        child.setRecipient(recipient);
        String request = new ObjectMapper().writeValueAsString(child);
        Child deserialisedChild = new ObjectMapper().readValue(request, Child.class);
        SomeEndPoint someEndPoint = (SomeEndPoint) deserialisedChild.getRecipient().getEndpointDetails();
        Assert.assertEquals(someEndPoint.getSomeToken(), endPoint.getSomeToken());
    }

Solution

  • I figured that the Lombok annotation @Jacksonized was the culprit here. Removing it solved the issue. To over-simplify, @Jacksonized interferes with how Jackson does deserialization by overriding a few things. It automatically configures the generated builder class to be used by Jackson's deserialization.