当前位置: 首页 > 知识库问答 >
问题:

java.time,ISO 8601,无毫秒序列化

郭易安
2023-03-14

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

预期格式为:“2016-12-24T00:00:00Z”

我正在使用杰克逊的JavaTimeModule,WRITE_DATES_AS_TIMESTAMPS设置为false

但这会打印毫秒。

所以我尝试使用objectMapper.set日期格式,这没有改变任何东西。

我目前的解决方法是这样的:

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

我正在重写<code>Instant的默认序列化程序。类</code>。

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

共有3个答案

彭琛
2023-03-14

这里有一些格式化< code>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())
汪胤
2023-03-14

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

你不会看到任何使用即时分区日期时间的副作用,因为杰克逊单独序列化区域id,默认情况下是禁用的。所以从技术上讲,这类似于将格式化程序应用于< code>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);
    }
}
史淇
2023-03-14

只需在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); 

输出

{ "即时":" 2016-11-10 06:03:06"}

您可以使用<code>Jackson2ObjectMapperBuilder</code>来构建它。

您只需要添加您想要的dateFormata。它将类似于下一步:

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();
 类似资料:
  • 问题内容: 很好,但这忽略了毫秒,如何在不使用非线程安全的情况下获取日期呢? https://github.com/FasterXML/jackson- databind/blob/master/src/main/java/com/fasterxml/jackson/databind/util/ISO8601DateFormat.java 问题答案: Calls ,反过来又调用- 参数告诉Jack

  • 问题内容: 我正在编写一个赛车应用程序,想要将大量毫秒转换为minutes:seconds.milliseconds(例如)。目前,我只是通过数学()进行运算,然后求余数并进一步除法,依此类推,但是我发现它时不时关闭1毫秒。我知道这听起来似乎没什么大不了的,但是我试图找到和的平均值,然后返回,这意味着它输入不正确,而应用程序的其余部分无法处理。 有没有一种方法使用或格式化毫秒到MM或类似的东西:s

  • 我尝试使用,但找不到有效地转换为毫秒的方法。我不是说这是最好的方法,如果你知道一些更好的,我会非常感谢一些指示。

  • 下面是一个演示这个问题的小提琴:https://dotnetfiddle.net/yi47ey 问题是,我们的客户机正在崩溃,因为他们期望一致的格式(例如,总是返回毫秒,即使在) 我找到了这个引用:https://www.w3.org/tr/note-datetime 其中规定: 允许几分之一秒的采用标准必须同时规定最小位数(大于或等于1的数字)和最大位数(最大位数可以说是“无限制”)。 那么,这

  • 问题内容: 我做了一些研究,但仍然找不到如何得到的日子…这是我得到的: 请帮助,我在数学上很烂,谢谢。 问题答案: 如果您没有另一个大于天的时间间隔: 如果您还有几个星期: 如果可能的话,最好避免使用几个月和几年,因为它们没有明确定义的固定长度。严格来说,两天都没有:夏令时意味着天的长度可以不是24小时。

  • 问题内容: 在Mac OS X(Mavericks)上的Java 8(b132)的第一个发行版中,使用新包的此代码有效: 渲染: 但是,当我在DateTimeFormatter类doc中指定的几分之一秒内添加“ SS”(并输入“ 55”)时,将引发异常: 文档说严格模式是默认使用的,并且需要与输入数字相同数量的格式字符。所以我很困惑为什么这段代码失败: 使用文档(“ 978”)中的示例的另一个示例