【问题标题】:is it possible to use Jackson with nanoseconds value是否可以使用具有纳秒值的杰克逊
【发布时间】:2015-01-08 18:36:33
【问题描述】:

在从对象解析到 json 时,我经历了最糟糕的时间来处理纳秒,反之亦然。我创建了杰克逊最简单的用法,但我无法获得纳秒。下面是我的演示。 fastxml FAQ 中有三个与我的案例相关的重要声明。前两个给了我工作的诀窍,第三个告诉我不要使用sql.Date,但sql.timestampsql.Date 的“儿子”。

问题是:

首先, mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,true)@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss.SSSSSS") 完全无效。我可以放falsetrue,甚至不使用mapper.configure,使用或不使用@JsonFormat,结果都是一样的,

其次,如果我只尝试反序列化,我的意思是,在user.json 中输入值2015-01-07 11:37:52.390452 并只运行mapper.readValue 我会得到值2015-01-07 11:44:22.452,所以我错过了确切的值,因为 Jacskon 向上取整.

来自http://wiki.fasterxml.com/JacksonFAQDateHandling

1 - Feature.WRITE_DATES_AS_TIMESTAMPS,假);禁止使用 时间戳(数字),而是使用符合 [ISO-8601] 的 表示法,其输出如下: “1970-01-01T00:00:00.000+0000”。

2 - 您可以通过传递 java.text.DateFormat 来配置格式

3 - 永远不要使用 java.sql.Date!

//宝乔

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
}

//主类

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(仅相关部分)

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

//控制台

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]

【问题讨论】:

    标签: java json datetime jackson fasterxml


    【解决方案1】:

    是的,可以使用具有纳秒值的 Jackson;要在 Java 8 中保留纳秒,您可以使用 java.util.Datejava.sql.Timestamp(假设您没有禁用默认启用的 Jackson 配置 DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDSSerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)。

    在 Java 8 之前,您可以使用 java.math.BigDecimal 来存储自纪元以来的天数加上一天中的小数时间。或者只是将值保留在其字符串表示形式中。 Java 7 和之前的版本不保留纳秒的日期,只有毫秒。因此,如果您将该值转换为java.util.Date 或其子类之一,如java.sql.Timestamp,您将只能获得毫秒的精度。因此,java.text.DateFormat 在 Java 8 之前的环境中使用它来转换为任何类型的 java Date 时在这里没有用处。

    这里进一步讨论 java Timestamps 中的纳秒:java.sql.Timestamp way of storing NanoSeconds

    【讨论】:

    • 假设我有一个遗留应用程序,在域层有 100 个 pojo 类,我确实需要使用它们分别序列化和反序列化为 Json/Object(请接受这种情况)。它们都至少有一个 sql.timestamp 属性。杰克逊专家团队的推荐是什么?我应该将代码从 Timestamp 更改为 String 还是 BigDecimal?当面对纳秒级的时间时,这是杰克逊规范提出的真正解决方案吗? Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS") 打印纳秒。在这种情况下必须在 pojo 中真正使用 String 吗?
    • 另外,我是否应该考虑 mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS,true) / mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS,true) 不可行。我阅读了一些利用此功能的示例,但我绝对无法通过此功能使简单的 hello 单词生效。
    • 抱歉,Java 8 似乎在其 Date 类中增加了对纳秒的支持。我已经更新了我的答案以反映这一点。希望您的应用程序在 Java 8 上运行,以便您可以利用此增强功能。
    • 我从 Java 6 改成了 Java 8 但结果完全一样。
    猜你喜欢
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2013-04-22
    • 2014-08-22
    • 2017-07-28
    相关资源
    最近更新 更多