【问题标题】:Jackson deserialize date string to LongJackson 将日期字符串反序列化为 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 值

有什么提示吗?谢谢。

【问题讨论】:

    标签: java json jackson


    【解决方案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 方法)。全力以赴!并避免指定格式化程序以及额外的转换。
      猜你喜欢
      • 2020-05-20
      • 2015-03-23
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      相关资源
      最近更新 更多