Search code examples
javaspring-bootjackson

How is date mapping done via Jackson in a Spring Boot app


In spring boot rest controller how is a Date field mapped. Let us say we send in json {"receivedDate":"2024-05-15","num1":5}. How will it be mapped to a field in Java object having a property private Date receivedDate; (assuming java.util.Date)

we can consider, a simple class

public class SampleClass {
        Integer num1;
        Date receivedDate;
        //getters and setters
    }

and a Rest Controller in Spring Boot app,

public ResponseEntity getDetails(@RequestBody SampleClass sampleClass) {
     try {
        System.out.println("Execution of getDetails started. received date is: "+sampleClass.getReceivedDate());
...............}
....
}

I get result in my console as(I executed this api at 10:20 Am IST):

Execution of getDetails started. received date is: Thu May 16 05:30:00 IST 2024

So, the result contains 05:30:00 and not my present time. What if I wanted it to be just 00:00:00.0 instead of 05:30:00.0. I am confused because in some stackoverflow answers, I came to know that Jackson's default behaviour is to do as per UTC. But it is doing as per IST though I have no configuration done.


Solution

  • Jackson converts correctly, the root problem is that you use an outdated, legacy class, known for the issues it's causing.

    This has been asked countless times in different forms. Do not use java.util.Date, it is not actually a date, it is an instant since the epoch, the class is broken, misleading, causes many programmer errors, the API is deprecated for a reason.

    In addition, toString(), which you use implicitly when printing, silently applies the default timezone when formatting the output, adding to the confusion. Your format is actually a simple date, without a time component, use java.time.LocalDate instead, part of java.time, the modern java date-time API, available since java 8.

    @Data
    public class SampleClass {
      
      private Integer num1;
      private LocalDate receivedDate;
    }
    

    If you need to conform to another API, which requires java.util.Date, there are convenient methods to make the conversion correctly.

    Instant instantStartOfDay = sampleClass.getReceivedDate()
      .atStartOfDay()
      .toInstant(ZoneOffset.UTC);
    Date asDate = Date.from(instantStartOfDay);