杰克逊将即时序列化为纳秒级问题 [英] Jackson Serialize Instant to Nanosecond Issue

查看:265
本文介绍了杰克逊将即时序列化为纳秒级问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jackson序列化java.time.Instant,默认情况下启用WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS.

Jackson serialises java.time.Instant with WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS enabled by default.

它会产生这样的JSON

{ "timestamp":1421261297.356000000 }

我想知道是否有一种方法可以消除结尾处的零.我想要类似的东西:

I wonder if there's a way to get rid of the zeros at the end. I want something like:

{ "timestamp":1421261297.356 }

我尝试过:

mapper.configure( SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false );
mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true );

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

But this configuration changes it to millisecond representation 1421261297356. I want the seconds part and the fractional milliseconds part.

推荐答案

当我们使用Java 8 Time软件包和Jackson进行工作时,好主意是使用 InstantSerializer .当我们检查它的实现方式时,我们会发现在幕后

When we are working with Java 8 Time package and Jackson good idea is to use jackson-modules-java8 project which serves many serialisers and deserialisers ready to use. To enable it we need to register JavaTimeModule module. To serialise Instant InstantSerializer is used. When we check how it is implemented we will find out that behind scene DecimalUtils.toDecimal method is used. It looks like there is always zeros added at the end of nanoseconds value.

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

We can write our InstantSerializer which serialises it in desired way. Because classes in this project are not ready to easily extend we need to implement many unwanted methods and constructors. Also we need create in our project com.fasterxml.jackson.datatype.jsr310.ser package and create our implementation there. See below example:

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)) {
                String concatenated = getEpochSeconds.applyAsLong(value) + "." + getNanoseconds.applyAsInt(value);
                generator.writeNumber(new BigDecimal(concatenated));
                return;
            }
        }

        super.serialize(value, generator, provider);
    }
}

并举例说明如何使用它:

And example how to use it:

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}

如果要在所有情况下都消除所有零,请编写在ShortInstantSerializer类中声明的自己的getNanoseconds函数.

If you want to rid of all zeros in all cases write your own getNanoseconds function declared in ShortInstantSerializer class.

这篇关于杰克逊将即时序列化为纳秒级问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆