Jackson 将日期字符串反序列化为 Long

Posted

技术标签:

【中文标题】Jackson 将日期字符串反序列化为 Long【英文标题】:Jackson deserialize date string to Long 【发布时间】:2022-01-08 02:52:26 【问题描述】:

Java Jackson 能否将 json 字符串日期反序列化为 Java Long 字段(从纪元开始的毫秒数)?

这是一个要反序列化的json字段的例子:

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

这是 Java 类中的同一个字段,带有当前注解:

@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;

但是,发生了异常:

com.fasterxml.jackson.databind.exc.InvalidFormatException: 不能 从 String 反序列化 java.lang.Long 类型的值 “2022-01-02T06:49:05Z”:不是有效的 Long 值

有什么提示吗?谢谢。

【问题讨论】:

【参考方案1】:

Maurice 的答案是正确的,它只是使用了臭名昭著的麻烦和长期过时的 SimpleDateFormatDate 类。没有它们,deserialize 方法也简单得多:

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);
        
    


按照我的理解,反序列化程序应该抛出JsonProcessingException 的一些子类,以防解析错误。 InvalidFormatException 在这种情况下是一个合适的子类。

【讨论】:

【参考方案2】:

使用像这样的自定义日期反序列化器:

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);
        
    

接下来用@JsonDeserialize(using = CustomDateDeserializer.class)注释你的字段。

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

【讨论】:

请不要教年轻人使用早已过时且臭名昭著的麻烦SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。我们在java.time, the modern Java date and time API, 和它的DateTimeFormatter 中做得更好。您已经在使用 java.time(Instant 及其 toEpochMilli 方法)。全力以赴!并避免指定格式化程序以及额外的转换。

以上是关于Jackson 将日期字符串反序列化为 Long的主要内容,如果未能解决你的问题,请参考以下文章

Jackson - 将内部对象列表反序列化为更高级别的列表

Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)

漏洞通告Jackson框架反序列化漏洞通告

使用 Jackson 进行 DateTime 反序列化的默认时区(Joda-Time 模块)

Jackson:将枚举值序列化和反序列化为整数

Jackson 将额外字段反序列化为 Map