Jackson , java.time , ISO 8601 , 序列化不带毫秒

我使用的是 Jackson 2.8,需要与不允许在 ISO 8601 时间戳内显示毫秒的 API 进行通信。

预期的格式是这样的:"2016-12-24T00:00:00Z"

我正在使用Jackson的JavaTimeModule,设置为.WRITE_DATES_AS_TIMESTAMPSfalse

但这将打印几毫秒。

所以我试图使用没有改变任何东西的东西。objectMapper.setDateFormat

我目前的解决方法是:

ObjectMapper om = new ObjectMapper();

DateTimeFormatter dtf = 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(dtf.format(value));
    }
});

om.registerModule(jtm);

我正在覆盖工作的默认序列化程序。Instant.class


有没有使用一些配置参数来解决这个问题的好方法?


答案 1

更新:

只需在属性上方添加日期格式的批注即可。这很容易。@JsonFormatInstant

如果您有一个对象映射器,接下来有类似内容:JavaTimeModule

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

如果你有一个带有属性的类,你应该添加注释并放置没有毫秒的日期模式。接下来会这样:Instant@JsonFormat

public static class TestDate {

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss", timezone = "UTC")
    Instant instant;

    //getters & setters
}

因此,如果您将对象序列化为Json,它可以完美地工作:

String json = mapper.writeValueAsString(testDate);
System.out.println(json); 

输出

{“即时”:“2016-11-10 06:03:06”}


旧答案。我不知道为什么,但它不能正常工作:

您可以使用 来构建它。Jackson2ObjectMapperBuilder

您只需要添加所需的日期格式即可。这将是下一个:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

ObjectMapper mapper = Jackson2ObjectMapperBuilder
            .json()       
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 
            .modules(new JavaTimeModule())
            .dateFormat(dateFormat)
            .build();

答案 2

这是一个替代方法,您可以全局设置,但需要您将与即时格式化程序一起使用,因为我们无法为Java时间模块提供的序列化程序设置格式。ZonedDateTimeInstant

您不会看到立即使用分区日期时间的任何副作用,因为 jackson 单独序列化区域 ID 并且默认情况下处于禁用状态。因此,从技术上讲,这类似于将格式化程序应用于 。Instant

以这种方式使用时,序列化程序将序列化委托给指定的自定义格式并使用指定的自定义格式。ZonedDateTimeInstantBaseSerializer

@RunWith(JUnit4.class)
public class InstantNoMillisTest {

    private ObjectMapper objectMapper;

    @Before
    public void init() {
        JavaTimeModule module = new JavaTimeModule();
        ZonedDateTimeSerializer zonedDateTimeSerializer = new ZonedDateTimeSerializer(new DateTimeFormatterBuilder().appendInstant(0).toFormatter());
        module.addSerializer(ZonedDateTime.class, zonedDateTimeSerializer);
        module.addDeserializer(ZonedDateTime.class, InstantDeserializer.ZONED_DATE_TIME);

        objectMapper = Jackson2ObjectMapperBuilder.json()
                .modules(module)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .build();
    }

    @Test
    public void serialize() throws IOException {
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        String noMillis = objectMapper.writeValueAsString(zonedDateTime);
        System.out.print(noMillis);
    }

    @Test
    public void deserialize() throws IOException {
        String dateTime = "\"2017-10-26T12:54:59Z\"";
        ZonedDateTime noMillis = objectMapper.readValue(dateTime, ZonedDateTime.class);
        System.out.print(noMillis);
    }
}

推荐