如何使用Jackson来反序列化JS日期?


72

我从ExtJS获取日期字符串,其格式为:

“ 2011-04-08T09:00:00”

当我尝试反序列化此日期时,它将时区更改为“印度标准时间”(该时间增加+5:30)。这就是我反序列化日期的方式:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);

这样做也不会更改时区。我仍然在IST中得到日期:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);

如何以无时区麻烦的日期反序列化日期?

Answers:


138

我找到了解决方法,但与此同时,我需要在整个项目中注释每个日期的设置器。有没有一种方法可以在创建ObjectMapper时指定格式?

这是我所做的:

public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
    @Override
    public Date deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        String date = jsonParser.getText();
        try {
            return format.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }

}

并用以下注释每个Date字段的setter方法:

@JsonDeserialize(using = CustomJsonDateDeserializer.class)

1
格式中的“ T”是什么意思,不应该是“ yyyy-MM-dd HH:mm:ss”
Bryan Hunt 2012年

这是有效的日期时间模式。例如evenyyyy.MM.dd G 'at' HH:mm:ss zhh 'o''clock' a, zzzz是有效模式。
Varun Achar 2012年

9
“ T”采用格式,因为它使用的是日期时间格式的ISO 8601标准。您显然不需要使用ISO标准格式,但是在使用第三方库(例如ExtJS)时,它可以帮助实现兼容性。en.wikipedia.org/wiki/…–
Patrick

7
@jjb不,这确实是错误的。由于simpleDateFormatter并非线程安全的,并且jackons缓存了根级反序列化器(并且不能禁用),因此您必须按照Varun Achar的建议对每个日期使用不同的SimpleDateFormatter或同步反序列化方法(如果您使用字段SimpleDateFormatter。并且该字段不能是静态的。这是我见过的最讨厌的错误之一。
Snicolas 2013年

1
这很有帮助,非常感谢。由于我使用的是Java 8,因此我使用LocalDate发布了答案,请参阅stackoverflow.com/a/31810856/60518
蒂姆·布斯(TimBüthe)2015年

56

这对我有用-我正在使用杰克逊2.0.4

ObjectMapper objectMapper = new ObjectMapper();
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
objectMapper.setDateFormat(df);

10
或代替SimpleDateFormat,我使用新的ISO8601DateFormat(),它与大多数其他语言的默认设置(C#,Ruby等)兼容
Christopher Davies 2012年

3
setDateFormat是否已弃用?
Albert Cheng

2
我是杰克逊的新手,我想知道在哪里添加以上代码?
哈比尔

2
'objectMapper.setDateFormat(df);' 如果您仅具有在其中设置格式的实用程序或唯一的bean,那将是很好的选择,否则,无论何时何地,都必须记住对其进行设置。另外,DateFormat不是线程安全的!
朱塞佩·阿达尔多

1
ObjectMapper是线程安全的。每种配置只需要一个实例,即,如果需要2种不同的日期格式,则需要2个ObjectMapper对象,或者只需要一个对象,但是需要synchronize调用该setDateFormat方法。
Varun Achar 2014年

15

关于这个主题,有一个不错的博客:http : //www.baeldung.com/jackson-serialize-dates 使用@JsonFormat看起来是最简单的方法。

public class Event {
    public String name;

    @JsonFormat
      (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    public Date eventDate;
}

6

除了Varun Achar的答案外,这是我想出的Java 8变体,它使用java.time.LocalDate和ZonedDateTime代替了旧的java.util.Date类。

public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {

    @Override
    public LocalDate deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException {

        String string = jsonparser.getText();

        if(string.length() > 20) {
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(string);
            return zonedDateTime.toLocalDate();
        }

        return LocalDate.parse(string);
    }
  }

2
您可能可以配置和使用Jackson的JSR-310数据类型模块,而不用编写自己的解串器。
保罗

-2

@JsonFormat仅适用于您使用的杰克逊版本支持的标准格式。

例如:-与任何标准格式(“ yyyy-MM-dd'T'HH:mm:ss.SSSZ”,“ yyyy-MM-dd'T'HH:mm:ss.SSS'Z', EEE,dd MMM yyyy HH:mm:ss zzz“,” yyyy-MM-dd“))for jackson 2.8.6

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.