与杰克逊格式化

问题描述

我有一个 OffsetDateTime。 在 json 中使用 Jackson 我看到了这个值:

2021-03-01T22:21:02.8624372-05:00

在我使用的领域

@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ssZ")

显示此值

2021-03-01T22:21:02-0500

任何想法

2021-03-01T22:21:02-05:00

解决方法

我在使用 onCreateView 时遇到了类似的问题。在那里,我覆盖了 .observe(getViewLifecycleOwner() to get the Lifecycle specifically associated with the Fragment's view,which is the correct scope for any Observer that updates your Fragment's UI (such as your 序列化程序,并使用了这样的自定义 Instant

Instant

但您也应该能够在该特定字段上使用 JavaTimeModule 而不是 DateTimeFormatter

ObjectMapper objectMapper = new ObjectMapper();
        
DateTimeFormatter instantFormatter = new DateTimeFormatterBuilder()
    .appendInstant(0)
    .toFormatter();
        
JavaTimeModule jtm = new JavaTimeModule();
jtm.addSerializer(Instant.class,new JsonSerializer<Instant>() {
    @Override
    public void serialize(Instant value,JsonGenerator gen,SerializerProvider serializers) throws IOException,JsonProcessingException {
        gen.writeString(instantFormatter.format(value));
    }
});

objectMapper.registerModule(jtm);

DateTimeFormatterBuilder 让您轻松自定义格式

,

假设您已经在使用 JavaTimeModule(将 WRITE_DATES_AS_TIMESTAMPS 作为 false,在您的第一个代码段中产生输出),您只需在 @JsonFormat 中提供适当的日期模式{1}},即。

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZZZZZ")

pattern 在哪里

特定于数据类型的附加配置,可用于进一步优化格式化方面。例如,这可以确定用于 java.util.Date 序列化的低级格式字符串;但是,确切的使用取决于特定的 JsonSerializer

此处的“特定于日期类型”是 JsonSerializer 的序列化程序。由于您使用的是 JavaTimeModule(假设!!!),那就是 OffsetDateTimeSerializer@JsonFormat pattern 被解释为一个 DateTimeFormatter 模式,该模式声明

Offset Z:根据模式字母的数量格式化偏移量。一、二或三个字母输出小时和分钟,不带冒号,例如“+0130”。当偏移量为零时,输出将为“+0000”。四个字母输出局部偏移的完整形式,相当于Offset-O的四个字母。如果偏移为零,则输出将是相应的本地化偏移文本。 五个字母输出小时、分钟,如果非零,可选秒,带冒号。如果偏移为零,则输出“Z”。六个或更多字母抛出 IllegalArgumentException

,

嗯,有很多方法可以做到,下面的代码显示了简单的两种方法:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class JsonDateFormat {

    /*
     * Approach I
     */
    @SuppressWarnings("static-method")
    public String getCurrentDateTime() {
        return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.now());
    }

    /*
     * Approach II
     */
    @SuppressWarnings("static-method")
    @JsonSerialize(using = CustomDateTimeFormatter.class)
    public Date getCustomCurrentDateTime() {
        return new Date();
    }

    public static void main(final String[] args) throws JsonProcessingException {
        final JsonDateFormat jsonDateFormat = new JsonDateFormat();
        final String result = new ObjectMapper().writeValueAsString(jsonDateFormat);
        System.out.println(result);
    }

}

下面是自定义字段序列化器。

import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

public class CustomDateTimeFormatter extends StdSerializer<Date> {

    private static final long serialVersionUID = 1L;

    public CustomDateTimeFormatter() {
        this(null);
    }

    public CustomDateTimeFormatter(final Class<Date> t) {
        super(t);
    }

    @Override
    public void serialize(final Date date,final JsonGenerator jgen,final SerializerProvider provider) throws IOException {
        final String dateTime = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault()));
        jgen.writeObject(dateTime);
    }

}

最后,您还可以使用自定义 DateTimeFormatter。见参考DateTimeFormatter doesn't parse custom date format