Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it possible to use Jackson with nanoseconds value

I have had the worst imaginable time to work with nanoseconds while parsing from object to json and vice verse. I created the simplest possible use of Jackson and I can't get the nanoseconds. Below is my demonstration. There are three important statement in fasterxml FAQ that are related to my case. The first two give me the trick to make work and the third tells not to use sql.Date but sql.timestamp is "son" of sql.Date.

The issues are:

Firstly, mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,true) and @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss.SSSSSS") take no effect at all. I can place false, true, even not use mapper.configure, use or not @JsonFormat and the result will be the same,

Secondly, if I try only Deserialize, I mean, enter the value 2015-01-07 11:37:52.390452 in theuser.json and only run mapper.readValue I will get the value 2015-01-07 11:44:22.452, so I miss the exact value because Jacskon round up.

from http://wiki.fasterxml.com/JacksonFAQDateHandling

1 - Feature.WRITE_DATES_AS_TIMESTAMPS, false); which disable use of timestamps (numbers), and instead use a [ISO-8601 ]-compliant notation, which gets output as something like: "1970-01-01T00:00:00.000+0000".

2 - You can configure formatting by passing a java.text.DateFormat

3 - Please do NOT use java.sql.Date, ever!

//the pojo

package com.jim.core;


import java.sql.Timestamp;
import com.fasterxml.jackson.annotation.JsonFormat;


public class User {

       @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss.SSSSSS")
       private Timestamp tsFirstTry;

       private Timestamp tsSecondTry;   

       @Override
       public String toString() {
              return "User [tsFirstTry=" + tsFirstTry + ", tsSecondTry=" + tsSecondTry + "]";
       }

       //getters and setters
}

//main class

package com.jim.core;


import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class Main {
    public static void main(String[] args) {

          User user = new User();
          user.setTsFirstTry(Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date())));

          user.setTsSecondTry(Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date())));


          System.out.println("firstTryValue = "+ Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date())));

          System.out.println("secondTryValue = "+ Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date())));

          ObjectMapper mapper = new ObjectMapper();

          try {
                 //mapper.setTimeZone(TimeZone.getTimeZone("UTC"));
                 //mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,true);

                 //mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS,true);

                 mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"));

                 //Serialization - saving the created objects in the sequence of bytes.
                 mapper.writeValue(new File("c:\\temp\\user.json"), user);
                 System.out.println("Serialized Outcome = " + mapper.writeValueAsString(user));

                 //Deserialization - Retrieving those saved bytes into the form of original object.
                 user = mapper.readValue(new File("c:\\temp\\user.json"), User.class);
                 System.out.println("Deserialized Outcome = " + user);


          } catch (IOException e) {
                 e.printStackTrace();
          }
    }
}

//pom (relevant part only)

<properties>
   <java-version>1.6</java-version>
   <jackson.databind-version>2.2.3</jackson.databind-version>
</properties>
<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.databind-version}</version>
    </dependency>

//Console

firstTryValue = 2015-01-08 11:31:53.000773
secondTryValue = 2015-01-08 11:31:53.000773

Serialized Outcome = {"tsFirstTry":"2015-01-08 17:31:53.000000","tsSecondTry":"2015-01-08 11:31:53.000000"}

Deserialized Outcome = User [tsFirstTry=2015-01-08 11:31:53.0, tsSecondTry=2015-01-08 11:31:53.0]
like image 283
Jim C Avatar asked Jan 08 '15 18:01

Jim C


People also ask

How does Jackson handle a single value Array?

if enable Jackson will accept a single value as an array. If disabled, then the exception will be thrown. If enabled, it will unwrap a single value array and deserialize it into the corresponding datatype. If disabled, the exception will be thrown. If enabled, it will unwrap the root value.

How to unpack the nested owner property in Jackson?

Then to map ownerName, we unpack the nested owner object to a Map and extract its name property. We can instruct Jackson to unpack the nested property by using a combination of @JsonProperty and some custom logic that we add to our Product class:

How do you read a JSON object in Jackson?

Jackson allows you to read JSON into a tree model: Java objects that represent JSON objects, arrays and values. These objects are called things like JsonNode or JsonArray and are provided by Jackson. Jackson uses a class called ObjectMapper as its main entrypoint.

Where can I find the latest version of Jackson databind?

Maven Dependency Let's first add the following dependency to pom.xml: We can find the latest versions of jackson-databind on Maven Central. 3. JSON Source Consider the following JSON as the source material for our examples. While the structure is contrived, note that we include properties that are nested two levels deep: 4. Simplified Domain Model


1 Answers

Yes, it is possible to use Jackson with nanoseconds value; to preserve nanoseconds in Java 8 you can use java.util.Date or java.sql.Timestamp (assuming you haven't disabled Jackson configuration DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS and SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, which are enabled by default).

Before Java 8 you can use a java.math.BigDecimal to store the number of days since epoch plus fractional time of day. Or just keep the value in its String representation. Java 7 and prior versions don't keep nanoseconds in dates, only milliseconds. So if you convert the value to a java.util.Date or one of its subclasses like java.sql.Timestamp, you will have precision only to milliseconds. Therefore java.text.DateFormat is not useful here if you are using it to convert to any kind of java Date in a pre-Java 8 environment.

Here is a further discussion of nanoseconds in java Timestamps: java.sql.Timestamp way of storing NanoSeconds

like image 126
gknicker Avatar answered Oct 19 '22 15:10

gknicker