4

I'm making a REST API with an Angular2 frontend. In my Spring configuration for jackson I have set this spring.jackson.date-format=EEE MMM dd yyyy HH:mm:ss zzz (zzzz) because I use the bootstrap-datepicker plugin which outputs dates like this: Wed May 31 2017 00:00:00 GMT+0200 (W. Europe Daylight Time). When I try to post a date to a DTO which has variables like this one private Date defaultDatetime; The REST API returns a 400 Bad request error.

{"timestamp":"mer. mai 03 2017 14:16:47",
"status":400,
"error":"Bad Request",
"exception":"org.springframework.http.converter.HttpMessageNotReadableException",
"message":"Could not read document: Can not construct instance of java.util.Date from String value '2017-05-01T22:00:00.000Z': not a valid representation (error: Failed to parse Date value '2017-05-01T22:00:00.000Z': Unparseable date: \"2017-05-01T22:00:00.000Z\")\n at [Source: java.io.PushbackInputStream@77b19daf; line: 1, column: 68] (through reference chain: ch.heigvd.form.api.dto.FormDTO[\"fields\"]->java.util.ArrayList[0]->ch.heigvd.form.api.dto.field.DateFieldDTO[\"defaultDate\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.Date from String value '2017-05-01T22:00:00.000Z': not a valid representation (error: Failed to parse Date value '2017-05-01T22:00:00.000Z': Unparseable date: \"2017-05-01T22:00:00.000Z\")\n at [Source: java.io.PushbackInputStream@77b19daf; line: 1, column: 68] (through reference chain: ch.heigvd.form.api.dto.FormDTO[\"fields\"]->java.util.ArrayList[0]->ch.heigvd.form.api.dto.field.DateFieldDTO[\"defaultDate\"])",
"path":"/api/forms"}

Any idea what kind of date-format I should put for jackson deserializatrion? Or should I change the format directly in the frontend?

Update

I got it working with a custom serializer. This is the configuration in the properties file.

spring.jackson.date-format=ch.heigvd.form.configuration.CustomJsonDateDeserializer spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false

This is the serializer:

public class CustomJsonDateDeserializer extends ISO8601DateFormat {

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        toAppendTo.append(format.format(date));
        return toAppendTo;
    }

    @Override
    public Date parse(String source, ParsePosition pos) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        try {
            return format.parse(source);
        } catch (ParseException var4) {
            return null;
        }
    }

}
1
  • 1
    I'm pretty sure that boostrsrap-datepicker returns js Date() object. When you make backend request it makes JSON.stringify(date), that returns string as "2017-05-03T15:07:34.056Z". Same is reflected in error message that you got. So set Jackson format to be able to parse that format. Commented May 3, 2017 at 15:09

1 Answer 1

2

You can do either of the two options, Option 1: since it returns ISOFormat, write your own deserializer.

@JsonDeserialize(using=CustomerDateAndTimeDeserialize .class)
public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
    @Override
    public Date deserialize(JsonParser jsonparser,
            DeserializationContext deserializationcontext) throws IOException, JsonProcessingException {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        String date = jsonparser.getText();
        try {
            return format.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }
}

Annotate each setter everywhere with

@JsonDeserialize(using = CustomJsonDateDeserializer.class)

Option 2: Change your format to match ISO String format.

spring.jackson.date-format=YYYY-MM-dd'T'HH:mm:ss.SSS'Z'
Sign up to request clarification or add additional context in comments.

5 Comments

I tried option 2 but I still got an error at first. I edited the property to spring.jackson.date-format=YYYY-MM-dd'T'HH:mm:ss.SSS'Z' and it seems to work now. Thank you!
I just realised that the date deserialized by jackson is not the same as the one given. When the frontend sends 2017-05-16T22:00:00.000Z, it always deserialize it to 2017-01-02T23:00:00.000Z. Should I try option 1?
@Servietsky : strange, yes Option 1 is full proof :). i will also try this replicating ur issue.
How can I apply the option 1 to every class. Every date I will deserialize will have the same format.
I got it working with some kind of custom serializer. I also replaced the YYYY with yyyy, I don't know if it changed anything. You can see it in my original post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.