1

I have legacy data coming in to my API as part of UserRequest model like

@PostMapping
public MyResponse saveUser(@Valid @RequestBody UserRequest userRequest) {
   ...
}

UserRequest class uses OffsetDateTime for dateRegistered field:

public class UserRequest {
   ...
   OffsetDateTime birthDate;
   ...
}

The problem I am having is that the data is coming into the API using below format for dateRegistered field:

{
    "last-name":"Mikel",
    "birth-date":"20200716"
}

So, the string representation "20200716" from JSON request needs to be somehow converted to OffsetDateTime like "2020-07-16T00:00:00Z" (the time portion and offset is set to 0s).

By default, the "20200716":

{
    "last-name":"Mikel",
    "birth-date":"20200716"
}

, gets converted to OffsetDateTime value of

{
    "last-name": "Mikel",
    "birth-date": "1970-08-22T19:18:36Z"
}

, which is obviously way off.

How do I convert a string representation of date in Json field like "20200716" to its OffsetDateTime representation like "2020-07-16T00:00:00Z" or "2020-07-16T00:00:00.000+00:00"?

I was trying to annotate my OffsetDateTime field with @JsonFormat("yyyyMMdd") but that is throwing exception like: JSON parse error: Cannot deserialize value of type java.time.OffsetDateTime from String "20200716".

pixel
  • 9,653
  • 16
  • 82
  • 149

3 Answers3

1

you don't need a JSON annotation. You need to adjust the setter as follow.

public class MedicalCandidateRequest {
   
    private OffsetDateTime dateRegistered;
   
    public OffsetDateTime getDateRegistered() {
        return dateRegistered;
    }
  
    public void setDateRegistered(String dateString) {
        final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSxx";
        DateTimeFormatter dtFormatter = DateTimeFormatter.ofPattern(pattern);
        this.dateRegistered = OffsetDateTime.parse(dateString, dtFormatter );
    }
}
Geeth
  • 541
  • 3
  • 12
  • Thanks but that errors out with `java.time.format.DateTimeParseException: Text '20200716' could not be parsed at index 0` – pixel Jun 14 '22 at 15:15
0

Change the parameter of the setter method to a String and do the conversion yourself.

public void setDateRegistered(String value) {
   this.dateRegistered = doConversionHere(value);
}
CaptainPyscho
  • 338
  • 1
  • 7
0

Thanks for suggestions but I have decided to go with my own implementation.

I provided a custom deserializer like:

public class CustomDateDeserializer extends JsonDeserializer<OffsetDateTime> {

    private static final String PATTERN = "yyyyMMdd";

    private final DateTimeFormatter formatter;

    public CustomDateDeserializer() {
        this.formatter = DateTimeFormatter.ofPattern(PATTERN);
    }

    @Override
    public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException, JacksonException {

        LocalDate localDate = LocalDate.parse(parser.getText), formatter);
        OffsetDateTime offsetDateTime = OffsetDateTime.of(localDate, LocalTime.MIDNIGHT, ZoneOffset.UTC);

        return offsetDateTime;
    }
}

, which I then use to annotate my model field like:

@JsonDeserialize(using = CustomDateDeserializer.class)
private OffsetDateTime birthDate;
pixel
  • 9,653
  • 16
  • 82
  • 149