pasaba por aqui
pasaba por aqui

Reputation: 3539

Jackson deserialize date string to Long

Can Java Jackson deserialize a json string date into a Java Long field (milliseconds from epoch)?

This is an example of json field to be deserialized:

"timestamp": "2022-01-02T03:04:05Z",

and this is the same field in the Java class, with the current annotations:

@JsonFormat(shape = JsonFormat.Shape.NUMBER, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
@JsonProperty("timestamp") 
@JsonPropertyDescription("blah, blah\r\n")
public Long timestamp;

However, an exception happens:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.lang.Long from String "2022-01-02T06:49:05Z": not a valid Long value

Any hint? Thanks.

Upvotes: 1

Views: 2794

Answers (2)

Anonymous
Anonymous

Reputation: 86379

The answer by Maurice is correct, it only suffers from using the notoriously troublesome and long outdated SimpleDateFormat and Date classes. Also the deserialize method is much simpler without them:

public class LongTimestampDeserializer extends StdDeserializer<Long> {

    public LongTimestampDeserializer() {
        this(null);
    }

    public LongTimestampDeserializer(Class<?> vc) {
        super(vc);
    }

    /** @throws InvalidFormatException If the timestamp cannot be parsed as an Instant */
    @Override
    public Long deserialize(JsonParser parser, DeserializationContext ctxt)
            throws IOException {
        String timestamp = parser.getText();
        try {
            return Instant.parse(timestamp).toEpochMilli();
        }
        catch (DateTimeParseException dtpe) {
            throw new InvalidFormatException(
                    parser, dtpe.getMessage(), timestamp, Long.class);
        }
    }

}

The way I understand it the deserializer should throw some subclass of JsonProcessingException in case of a parsing error. InvalidFormatException is a suitable subclass in this case.

Upvotes: 3

Maurice
Maurice

Reputation: 7401

Use a custom date deserializer like this one:

public class CustomDateDeserializer extends StdDeserializer<Long> {

    private SimpleDateFormat formatter = 
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");

    public CustomDateDeserializer() {
        this(null);
    }

    public CustomDateDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Long deserialize(JsonParser jsonparser, DeserializationContext context)  
      throws IOException, JsonProcessingException {
        String date = jsonparser.getText();
        try {
            return formatter.parse(date).toInstant().toEpochMilli();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

Next annotate your field with @JsonDeserialize(using = CustomDateDeserializer.class).

@JsonDeserialize(using = CustomDateDeserializer.class)
public Long timestamp;

Upvotes: 2

Related Questions