question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow Instant to be serialized as epochSecond without the fraction part

See original GitHub issue

I have an Instant field that represents an epoch timestamp in seconds.

    @JsonProperty("registered_at")
    @JsonFormat(shape = JsonFormat.Shape.NUMBER)
    private Instant registeredAt;

the mapper is configured this way

    .featuresToDisable(ADJUST_DATES_TO_CONTEXT_TIME_ZONE,
                       FAIL_ON_UNKNOWN_PROPERTIES,
                       WRITE_DATES_AS_TIMESTAMPS,
                       SORT_PROPERTIES_ALPHABETICALLY)

However when this gets serialized as

"registered_at" : 1420324047.000000000

By looking at the code there’s no way to serialize this value as epoch seconds using the standard mechanism.

InstantSerializerBase.serialize(T value, JsonGenerator generator, SerializerProvider provider)

        if (useTimestamp(provider)) {
            if (useNanoseconds(provider)) {
                generator.writeNumber(DecimalUtils.toBigDecimal(
                        getEpochSeconds.applyAsLong(value), getNanoseconds.applyAsInt(value)
                ));
                return;
            }
            generator.writeNumber(getEpochMillis.applyAsLong(value));
            return;
        }

The only option is to use :

    @JsonGetter("registered_at")
    public long getRegisteredAtEpoch() {
        return registeredAt.getEpochSecond();
    }

It could be nice if there could be way to tell jackson to avoid serializing the fraction part.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:1
  • Comments:20 (15 by maintainers)

github_iconTop GitHub Comments

2reactions
jsnelgrocommented, Oct 19, 2022

Just wanted to post my solution here, since this was the first thread that came up in a web search and I didn’t see an explicit code snippet that solved my problem. I needed to serialize as epoch millisecond without globally configuring the ObjectMapper. This is what solved my use case (I’m working in Kotlin):

data class MyPojo(
  @JsonFormat(without = [JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS])
  val timestamp: Instant
)
1reaction
nniesencommented, Oct 30, 2020

I think it should be epoch millis for this change to be useful. Epoch millis makes the the timestamps portable with regard to both Java and JavaScript; which are the likely producers and consumers on both ends of the request.

Default serializer: Instant.toEpochMilli() Default deserializer: Instant.ofEpochMilli(long epochMilli)

I currently use this configuration:

jackson:
  serialization: # com.fasterxml.jackson.databind.SerializationFeature
    WRITE_DATES_AS_TIMESTAMPS: true # Instant.toEpochMillis()
    WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS: false
  deserialization: # com.fasterxml.jackson.databind.DeserializationFeature
    READ_DATE_TIMESTAMPS_AS_NANOSECONDS: false

This makes the timestamps easily transferrable between the platforms with consistent APIs.

Java:

long value = 1551461407999L
Instant deserialized = Instant.ofEpochMilli(value)
System.out.println(deserialized)
long serialized = deserialized.toEpochMilli()
System.out.println(serialized)
System.out.println(serialized == value)
System.out.println(Instant.ofEpochMilli(1551461407999L).toEpochMilli() == 1551461407999L)

Javascript:

var value = 1551461407999;
var deserialized = new Date(value);
console.log(deserialized.toISOString());
var serialized = deserialized.valueOf();
console.log(serialized);
console.log(serialized == value);
console.log(new Date(1551461407999).valueOf() == 1551461407999);

Moment.js:

var value = 1551461407999;
var deserialized = new moment(value);
console.log(deserialized.toISOString());
var serialized = deserialized.valueOf();
console.log(serialized);
console.log(serialized == value);
console.log(new moment(1551461407999).valueOf() == 1551461407999);

All 3 produce:

2019-03-01T17:30:07.999Z
1551461407999
true
true

If some needs/wants epoch seconds, they can use the Instant/Date APIs to truncate to seconds when creating the initial value.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Jackson Serialize Instant to Nanosecond Issue - Stack Overflow
But this configuration changes it to millisecond representation 1421261297356 . I want the seconds part and the fractional milliseconds part.
Read more >
Instant (Java Platform SE 8 ) - Oracle Help Center
Obtains an instance of Instant using seconds from the epoch of 1970-01-01T00:00:00Z and nanosecond fraction of second. This method allows an arbitrary number...
Read more >
Serialize Timestamp To EpochSecond with Jackson
The Instant class provides the epoch second and the nanosecond of that second. We need to disable the nanosecond from the serialization process ......
Read more >
Issues · FasterXML/jackson-modules-java8 · GitHub
Serialize OffsetDateTime is always using the time zone in ObjectMapper if I set ... Allow Instant to be serialized as epochSecond without the...
Read more >
java.time.Instant.java Source code - Java2s.com
For both the epoch-second and nanosecond parts, a larger value is always later ... Serializable { /** * Constant for the 1970-01-01T00:00:00Z epoch...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found