Home > database >  Jackson deserialize date string to Long
Jackson deserialize date string to Long

Time:12-02

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.

CodePudding user response:

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.

CodePudding user response:

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;
  • Related