簡體   English   中英

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

[英]Jackson , java.time , ISO 8601 , serialize without milliseconds

我正在使用Jackson 2.8並且需要與ISO 8601時間戳內不允許毫秒的API進行通信。

預期格式為: "2016-12-24T00:00:00Z"

我正在使用Jackson的JavaTimeModule, WRITE_DATES_AS_TIMESTAMPS設置為false

但這將打印毫秒。

所以我嘗試使用沒有改變任何東西的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的默認序列化Instant.class


有沒有什么好辦法使用一些配置參數來解決這個問題?

更新:

只需在Instant屬性上方添加日期格式的@JsonFormat注釋即可。 這很容易。

如果你有一個帶有JavaTimeModule的ObjectMapper,就像下一個:

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

產量

{“instant”:“2016-11-10 06:03:06”}


老答案。 我不知道為什么,但它不起作用:

您可以使用Jackson2ObjectMapperBuilder來構建它。

您只需要添加所需的dateFormat。 這將是下一個:

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

這是一個可以全局設置的替代方法,但是需要您使用ZonedDateTime和即時格式化程序,因為我們無法設置隨Java Time Module提供的Instant Serializer的格式。

您不會看到使用分區日期時間為即時的任何副作用,因為傑克遜分別序列化區域ID並默認禁用。 從技術上講,這類似於將格式化程序應用於Instant

以這種方式使用時, ZonedDateTime序列化程序將序列化委派給InstantBaseSerializer並使用指定的自定義格式。

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

這里有一些格式化Instant字段的Kotlin代碼,因此它們不包含毫秒,您可以使用自定義日期格式化程序

ObjectMapper().apply {
        val javaTimeModule = JavaTimeModule()
        javaTimeModule.addSerializer(Instant::class.java, Iso8601WithoutMillisInstantSerializer())
        registerModule(javaTimeModule)
        disable(WRITE_DATES_AS_TIMESTAMPS)
    }

private class Iso8601WithoutMillisInstantSerializer
        : InstantSerializer(InstantSerializer.INSTANCE, false, DateTimeFormatterBuilder().appendInstant(0).toFormatter())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM