I have created this deserializer to be managed in a centralized custom object mapper bean, and it works fine, but I'm not able to deserialize the dates that are coming in this format '2017-04-04T08:04+0000' into the correct OffsetDateTime format - getting the following exception:
Text '2017-04-04T08:04+0000' could not be parsed, unparsed text found at index 19 (through reference chain: earth.green.integration_models.sh.Prediction$PredictionBuilder["created"])
I have searched lots of formats on the internet and none of them have worked, so if any of you know which format can I use to deserialize this date, will be very helpful.
public class OffsetDateTimeDeserializer
extends JsonDeserializer<OffsetDateTime>
{
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm[XXX][XXXX]" );
@Override
public OffsetDateTime deserialize( final JsonParser parser,
final DeserializationContext context )
throws IOException
{
formatter.withZone( ZoneId.of( "GMT") );
return OffsetDateTime.parse( parser.readValueAs( String.class ), formatter );
}
}
private final DateTimeFormatter formatter
= DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mmxx" );
When offset zero is given as +0000
rather than Z
, use lower case xx
.
Demonstration:
String valueAsString = "2017-04-04T08:04+0000";
OffsetDateTime deserialized = OffsetDateTime.parse( valueAsString, formatter );
System.out.println( deserialized );
This outputs:
2017-04-04T08:04Z
What went wrong in your code? From the documentation:
Offset X and x: This formats the offset based on the number of pattern letters. One letter outputs just the hour, such as '+01', unless the minute is non-zero in which case the minute is also output, such as '+0130'. Two letters outputs the hour and minute, without a colon, such as '+0130'. Three letters outputs the hour and minute, with a colon, such as '+01:30'. Four letters outputs the hour and minute and optional second, without a colon, such as '+013015'. Five letters outputs the hour and minute and optional second, with a colon, such as '+01:30:15'. …
According to this XXX
should try to parse an offset like +00:00
, with a colon, and fail since there is no colon in the offset in the parsed string. Next XXXX
should try either +0000
or +000000
since the seconds are optional, so should succeed. Which it also did on my computer. So explanations I can think of include:
XXX
parsed just +00
(the hours) and left the final 00
unparsed, after which XXXX
couldn’t do anything. It’s not a bug I’ve heard of, so pure speculation and not really likely. If this were the problem, just swapping [XXX]
and [XXXX]
should remedy it.)Edit: Do you know what can I want to get it deserialized in the same format as the string, just to serialize back and compare the two strings and look that they are equal?
OffsetDateTime
, deserialize it back and check that the two OffsetDateTime
objects are equal.xx
in the format pattern string. This prevents offset zero being rendered as Z
. Meaning that 2017-04-04T08:04+0000
will be printed back, the same string as you started out from.