3

I have a spring boot application where the timezone of a ZonedDateTime field gets converted to UTC when a RESTful API receives a request body that has a ZonedDateTime field. How can I make the application keep the original timezone only for one field and convert it to UTC for all other fields?

I know we can disable this for all fields by adding the below line to the properties file, but in my case I don't want to disable it for all fields, I just want to disable it for one field.

spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE = false

MA1
  • 926
  • 10
  • 28

1 Answers1

2

You can use JsonFormat annotation:

@JsonFormat(without = {ADJUST_DATES_TO_CONTEXT_TIME_ZONE})

Take a look on below example:

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.File;
import java.io.IOException;
import java.time.ZonedDateTime;

import static com.fasterxml.jackson.annotation.JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE;

public class ZonedJsonApp {

    public static void main(String[] args) throws IOException {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        JsonMapper mapper = JsonMapper.builder()
                .addModule(new JavaTimeModule())
                .build();
        System.out.println(mapper.readValue(jsonFile, ZonedPojo.class));
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
class ZonedPojo {
    private ZonedDateTime with;

    @JsonFormat(without = {ADJUST_DATES_TO_CONTEXT_TIME_ZONE})
    private ZonedDateTime without;
}

Which for below JSON payload:

{
  "with": "2007-12-03T10:15:30+04:00",
  "without": "2007-12-03T10:15:30+04:00"
}

Prints:

ZonedPojo(with=2007-12-03T06:15:30Z[UTC], without=2007-12-03T10:15:30+04:00)
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Unfortunately it didn't work for me, I added the same exact code to my project and run the code. Here is what I got: ZonedPojo(with=2007-12-03T06:15:30Z[UTC], without=2007-12-03T06:15:30Z[UTC]) – MA1 Aug 28 '21 at 20:59
  • @MoA, which version of Jackson and Spring Boot do you use? – Michał Ziober Aug 28 '21 at 23:19
  • Spring boot version is '2.4.5'. I'm also using the dependencies 'org.springframework.boot:spring-boot-starter-webflux' and "io.springfox:springfox-boot-starter:3.0.0" in my project. I don't use Jackson directly, it's included with the spring boot, the version is com.fasterxml.jackson.core:jackson-databind:2.11.4 – MA1 Aug 29 '21 at 03:13
  • @MoA, I tested it with `Jackson:2.11.4` and it works properly. Are you sure all imports come from the right libraries and look the same like in my example? – Michał Ziober Aug 30 '21 at 08:28
  • 1
    I had to add the dependency below explicitly to make it work, unfortunately the transitive Jackson dependency that is included in the spring boot didn't work. implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.12.4' – MA1 Aug 30 '21 at 14:49
  • 1
    @MoA, I'm glad to hear that. It is always worth to add all [Java 8 modules](https://github.com/FasterXML/jackson-modules-java8), [Force Jackson serialize LocalDate to Array](https://stackoverflow.com/questions/62423389/force-jackson-serialize-localdate-to-array/62426300#62426300) – Michał Ziober Aug 30 '21 at 15:29
  • Thanks a lot for this response. Can you please tell me how to achieve the same when using the `Instant` datetime format instead of `ZonedDateTime`? – BATMAN_2008 Apr 13 '22 at 08:40