杰克逊将即时序列化为纳秒级问题

Jackson串行化java.time.InstantWRITE_DATE_TIMESTAMPS_AS_NANOSECONDS默认启用。

它产生JSON像这样

{ "timestamp":1421261297.356000000 }

我想知道是否有一种方法可以消除最后的零。我想要类似的东西:

{ "timestamp":1421261297.356 }

我试过了:

mapper.configure( SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false );

mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true );

但是此配置将其更改为毫秒表示1421261297356。我想要秒部分和小数毫秒部分。

回答:

当我们使用Java 8Timepackage时,Jackson最好使用jackson-modules-

java8项目,该项目可以使用许多序列化程序和反序列化程序。要启用它,我们需要注册JavaTimeModule模块。要序列化Instant

InstantSerializer,请使用。当我们检查它的实现方式时,我们会发现在后台使用了DecimalUtils.toDecimal方法。看起来在纳秒值的末尾总是添加零。

我们可以编写InstantSerializer以所需方式对其进行序列化的代码。由于该项目中的类尚未准备好轻松扩展,因此我们需要实现许多不需要的方法和构造函数。另外,我们需要在项目com.fasterxml.jackson.datatype.jsr310.ser包中创建并在其中创建实现。请参见以下示例:

package com.fasterxml.jackson.datatype.jsr310.ser;

import com.fasterxml.jackson.annotation.JsonFormat;

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

import java.math.BigDecimal;

import java.time.Instant;

import java.time.format.DateTimeFormatter;

import java.util.function.ToIntFunction;

import java.util.function.ToLongFunction;

public class ShortInstantSerializer extends InstantSerializerBase<Instant> {

private ToLongFunction<Instant> getEpochSeconds = Instant::getEpochSecond;

private ToIntFunction<Instant> getNanoseconds = i -> i.getNano() / 1_000_000;

public ShortInstantSerializer() {

super(Instant.class, Instant::toEpochMilli, Instant::getEpochSecond, Instant::getNano, null);

}

protected ShortInstantSerializer(ShortInstantSerializer base, Boolean useTimestamp, Boolean useNanoseconds, DateTimeFormatter formatter) {

super(base, useTimestamp, useNanoseconds, formatter);

}

@Override

protected JSR310FormattedSerializerBase<?> withFormat(Boolean useTimestamp, DateTimeFormatter formatter, JsonFormat.Shape shape) {

return new ShortInstantSerializer(this, useTimestamp, null, formatter);

}

@Override

public void serialize(Instant value, JsonGenerator generator, SerializerProvider provider) throws IOException {

if (useTimestamp(provider)) {

if (useNanoseconds(provider)) {

generator.writeNumber(new BigDecimal(toShortVersion(value)));

return;

}

}

super.serialize(value, generator, provider);

}

private String toShortVersion(final Instant value) {

return getEpochSeconds.applyAsLong(value) + "." + padWithZeros(getNanoseconds.applyAsInt(value));

}

private String padWithZeros(final int value) {

return String.format("%1$3s", String.valueOf(value)).replace(' ', '0');

}

}

并举例说明如何使用它:

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.SerializationFeature;

import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import com.fasterxml.jackson.datatype.jsr310.ser.ShortInstantSerializer;

import java.time.Instant;

public class JsonApp {

public static void main(String[] args) throws Exception {

JavaTimeModule javaTimeModule = new JavaTimeModule();

javaTimeModule.addSerializer(Instant.class, new ShortInstantSerializer());

ObjectMapper mapper = new ObjectMapper();

mapper.registerModule(javaTimeModule);

mapper.disable(SerializationFeature.INDENT_OUTPUT);

System.out.println(mapper.writeValueAsString(new Element()));

}

}

class Element {

private Instant timestamp = Instant.now();

public Instant getTimestamp() {

return timestamp;

}

public void setTimestamp(Instant timestamp) {

this.timestamp = timestamp;

}

}

上面的代码打印:

{"timestamp":1559074287.223}

如果要在所有情况下都消除全零,则编写您自己的getNanosecondsShortInstantSerializer类中声明的函数。

以上是 杰克逊将即时序列化为纳秒级问题 的全部内容, 来源链接: utcz.com/qa/408014.html

回到顶部