2

I'm using Jackson to parse a JSON and the deserialization fails because of a date field defined as:

@JsonProperty("jcr:created")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z")
private Date created;

com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.util.Date from String "Wed Sep 14 2016 15:37:40 GMT+0200": expected format "EEE MMM dd yyyy HH:mm:ss 'GMT'Z"

The JSON content looks like this:

"jcr:created": "Thu Feb 04 2016 09:32:14 GMT+0100"

What's the issue with the pattern?

user66875
  • 2,772
  • 3
  • 29
  • 55
  • 2
    I recommend you don’t use `Date`. It was a poorly designed class and is long outdated. Can you use `OffsetDateTime` from [java.time, the modern Java date and til API](https://docs.oracle.com/javase/tutorial/datetime/index.html)? – Ole V.V. Apr 01 '23 at 14:17
  • 2
    A locale problem? Is it failing on computers with non-English default locale? – Ole V.V. Apr 01 '23 at 14:18
  • 2
    By the way, the work is so much easier if you textually exchange date-time values in standard [ISO 8601](https://en.m.wikipedia.org/wiki/ISO_8601) format. – Basil Bourque Apr 01 '23 at 14:46

1 Answers1

4

java.time

The java.util date-time API and their corresponding parsing/formatting type, SimpleDateFormat are outdated and error-prone. In March 2014, the modern Date-Time API was released as part of the Java 8 standard library which supplanted the legacy date-time API and since then it is strongly recommended to switch to java.time, the modern date-time API.

Also, never use date-time parsing/formatting API without specifying a Locale.

Solution using java.time

Since your date-time string has timezone information, you should praise it into ZonedDateTime.

@JsonProperty("jcr:created")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "EEE MMM dd yyyy HH:mm:ss VVXX", locale = Locale.ENGLISH)
private ZonedDateTime created;

Demo:

class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss VVXX", Locale.ENGLISH);
        String created = "Thu Feb 04 2016 09:32:14 GMT+0100";
        ZonedDateTime zdt = ZonedDateTime.parse(created, dtf);
        System.out.println(zdt);
    }
}

Output:

2016-02-04T08:32:14Z[GMT]

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

If for any reason, you want to carry on with the error-prone legacy API, simply include locale in the annotation

@JsonProperty("jcr:created")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z", locale = Locale.ENGLISH)
private Date created;

Demo:

class Main {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.ENGLISH);
        String created = "Thu Feb 04 2016 09:32:14 GMT+0100";
        Date date = sdf.parse(created);
        System.out.println(date);
    }
}

Output:

Thu Feb 04 08:32:14 GMT 2016

ONLINE DEMO

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • This works perfectly fine! Thanks a lot! Only thing is I get a "Attribute value must be constant" for the Locale.ENGLISH. Any idea why? – user66875 Apr 01 '23 at 15:48
  • Great! There should be no double quote around `Locale.ENGLISH`. Please check if you have made a typo. You can find more details [here](https://access.redhat.com/webassets/avalon/d/red-hat-jboss-enterprise-application-platform/7.2.beta/javadocs//com/fasterxml/jackson/annotation/JsonFormat.html#locale--). If you still face this issue, check if `locale = "en_GB"` resolves this issue. – Arvind Kumar Avinash Apr 01 '23 at 15:53
  • 1
    Ah no I don't have any quotes around it. I imported the Locale from java.util but intellij underlines it red with the error mentioned above. using `locale = "en"` solved it but I liked your way with the Locale.ENGLISH more :) – user66875 Apr 01 '23 at 16:00