0

Trying to deserialize date with specific pattern from json file.
Object which I want to receive from json file:

@Data
public class MyClass {
  @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  private LocalDateTime date;
}

Json file:

{
  "date" : "2017-01-01T00:00:59.000UTC"
}

Code example how I want to receive it:

ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);

Actual result:

com.fasterxml.jackson.databind.exc.InvalidFormatException: 
Cannot deserialize value of type `java.time.LocalDateTime` from String "2017-01-01T00:00:59.000UTC":
Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) 
Text '2017-01-01T00:00:59.000UTC' could not be parsed, unparsed text found at index 23
at [Source: (File); line: 2, column: 11] (through reference chain: com.example.MyClass["date"])

How to deserialize current date pattern?

Ilja Tarasovs
  • 181
  • 2
  • 13
  • `2017-01-01T00:00:59.000UTC` is a peculiar mixed format. What’s wrong with the international standard, [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)? – Ole V.V. Apr 29 '21 at 16:19

3 Answers3

2

Your date is in incorrect format (with UTC as text simply appended), but you can solve it by custom formatter.

public class Test {

  public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    MyClass localDateTime = objectMapper.readValue("{\"date\":\"2017-01-01T00:00:59.000UTC\"}", MyClass.class);
    System.out.println(localDateTime.date);
  }

  @Data
  public static class MyClass {
    @JsonDeserialize(using = CustomDeserializer.class)
    private LocalDateTime date;

  }

  public static class CustomDeserializer extends LocalDateTimeDeserializer {

    public CustomDeserializer() {
      super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

    protected CustomDeserializer(LocalDateTimeDeserializer base, Boolean leniency) {
      super(base, leniency);
    }

    @Override
    public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
      String substring = jsonParser.getText().substring(0, jsonParser.getText().indexOf("U"));
      return LocalDateTime.parse(substring, _formatter);
    }
  }

}
phil_g
  • 516
  • 6
  • 13
2

The date format that you are using is incorrect.

Instead of: yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'

it should be: yyyy-MM-dd'T'HH:mm:ss.SSSz

Secondly, you need to use @JsonFormat to specify the date format.

@JsonFormat which is defined in jackson-databind package gives you more control on how to format Date and Calendar values according to SimpleDateFormat.

By using this, the POJO MyClass would look something like this:

@Data
public class MyClass {
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSz", timezone = "UTC")
  @JsonDeserialize(using = LocalDateTimeDeserializer.class)
  private LocalDateTime date;
}

Now, if you try to deserialize using:

ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);
System.out.println(myClass);

Then the process would go through, producing a result something like this:

MyClass{date=2017-01-01T00:00:59.000}
Shyam Baitmangalkar
  • 1,075
  • 12
  • 18
  • Yes, this configuration works. Following two lines are enough to deserialize this json date: ```@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSz") @JsonDeserialize(using = LocalDateTimeDeserializer.class)``` but we lost the zone. – Ilja Tarasovs Apr 29 '21 at 11:45
  • Can you please elaborate on what did you mean by lost the zone? – Shyam Baitmangalkar Apr 29 '21 at 12:27
0

Try removing @JsonDeserialize. (In any case, you are trying to deserialize your date into LocalDateTime but it has time zone info, you would need to try ZonedDateTime or OffsetDateTime). And change the line

@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")

to

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")

Here is the link to the question that has a full answer for you: Spring Data JPA - ZonedDateTime format for json serialization

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
  • for `ZonedDateTime` or `OffsetDateTime` doesn't work throws following error: ```com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2017-01-01T00:00:59.000UTC')``` Because deserializer class is required. And there is no default deserializer classes provided for these type of date classes. – Ilja Tarasovs Apr 29 '21 at 11:41
  • Try to change 'Z' to 'O' in mask. So your mask would be "yyyy-MM-dd'T'HH:mm:ss.SSSO". See Javadoc for class DateTimeFormatter – Michael Gantman Apr 29 '21 at 13:38