FasterXML / jackson-modules-java8

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)
Apache License 2.0
400 stars 116 forks source link

Custom deserializer for `LocalDate` used via `@JsonDeserialize(using=)` is not being invoked #258

Closed sanchayddun closed 1 year ago

sanchayddun commented 1 year ago

I have a class

package com.walmart.polaris.schedule.rule.model.schedule;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.walmart.polaris.schedule.rule.constants.WorkerStatus;
import com.walmart.polaris.schedule.rule.model.common.WorkerType;
import com.walmart.polaris.schedule.rule.model.common.AvailabilityException;
import com.walmart.polaris.schedule.rule.model.common.Job;
import com.walmart.polaris.schedule.rule.model.common.Location;
import com.walmart.polaris.schedule.rule.model.common.PayType;
import com.walmart.polaris.schedule.rule.model.common.Shift;
import java.time.LocalDate;
import java.util.List;

import com.walmart.polaris.schedule.rule.util.DateDeserializer;
import com.walmart.polaris.schedule.rule.util.DateSereliazer;
import lombok.*;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ValidationRequest {
  @JsonAlias("id")
  private Long workerId;
  private String requestId;
  private List<Location> locations;

  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
  @JsonDeserialize(using = DateDeserializer.class)
  @JsonSerialize(using = DateSereliazer.class)
  private LocalDate birthDate;

  private WorkerStatus status;
  @JsonAlias("employmentType")
  private List<WorkerType> workerType;
  private List<PayType> payType;
  private List<AvailabilityException> availabilityExceptions;
  private List<Job> jobs;
  private List<Shift> schedules;
}

And I wrote a customDeserializer for one property birthDate which is of type LocalDate.

package com.walmart.polaris.schedule.rule.util;

import lombok.extern.slf4j.Slf4j;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;

import java.io.IOException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

@Slf4j
public class DateDeserializer extends JsonDeserializer<LocalDate> {

    public DateDeserializer() {
        this(null);
    }

    public DateDeserializer(Class<?> vc) {
        super();
    }
    @Override
    public LocalDate deserialize(JsonParser p, DeserializationContext ctx)
            throws IOException {
        String str = p.getText();
        try {
            return LocalDate.parse(str, DateTimeFormatter.ofPattern("dd-MM-yyyy"));
        } catch (DateTimeParseException e) {
            return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
    }
}

My use case is that the property birthDate can be of format dd-MM-yyyy or yyyy-MM-dd. Hence I tried to parse it using both patterns. But there seems to be some issue in this, the deserialize method is not being invoked. I also tried removing the @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") line from it, then also same issue is occuring. Can anyone help me? Or what am I doing wrong here?

cowtowncoder commented 1 year ago

@JsonFormat annotation should not be a problem, and @JsonDeserialize annotation looks legit.

What I would suggest checking is use of Lombok: perhaps it changes annotations during processing it does?

Alternatively if you can create a test case that does NOT use Lombok I could have a look (I do not troubleshoot reproductions with Lombok as an additional dependency -- but if you can get class definition after Lombok processing that'd be fine too).

cowtowncoder commented 1 year ago

At this point I cannot reproduce the issue: we would need a test case without Lombok (using class definition after Lombok has processed it). It is likely that there is a Lombok setting to make sure annotations get properly copied/added to generated classes, but I am not familiar enough with it to help.

Closing; may be re-opened/filed with a reproduction showing the issue without Lombok (or other 3rd party lib/framework) dependency.