【问题标题】:Why jackson formats date to yyyy-MM-dd instead of timestamp?为什么杰克逊将日期格式化为 yyyy-MM-dd 而不是时间戳?
【发布时间】:2015-09-06 22:33:13
【问题描述】:

我有我的第一个带有休息服务的春季项目。 只有一个问题我自己解决不了。我的“获取”请求以这种方式提供对象日期值:

{"id":6,"type":"Trainer","changed":"2015-06-20","created":"2015-06-19"}

但我希望它采用时间戳格式,因为我认为这是默认格式。

我的 PUT 请求中的输入日期按预期从时间戳格式解析。

我正在使用 springframework 4.1.6.RELEASE 和 fastxml.jackson 2.5.4 使用这些 spring 工件:spring-context、spring-webmvc、spring-jdbc

还有这些 fastxml 工件:jackson-core、jackson-databind

这是我的控制器方法:

@Override
@RequestMapping(value="/{id}", method=RequestMethod.GET)
@ResponseBody
public T getObject(@PathVariable("id") long id) {
    T obj = dao.getById(id);
    logger.debug("GET " + getClass().getSimpleName() + "." + id + ": " + obj);
    return obj;
}

我的 web.xml:

<?xml 

    version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
            /WEB-INF/spring/root-context.xml
            </param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <servlet>
            <servlet-name>appServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
                    /WEB-INF/spring/appServlet/servlet-context.xml
                    classpath:Beans.xml
                </param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>appServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

servlet-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="de.kreth.clubhelperbackend" />

    <mvc:annotation-driven />

    <mvc:resources mapping="/resources/**" location="/resources/" />

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" />

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

还有我的 Beans.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost/clubhelperbackend" />
        <property name="username" value="markus" />
        <property name="password" value="0773" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource" />
    </bean>

    <bean id="sqlForDialect" class="de.kreth.clubhelperbackend.SqlForMysql">
        <constructor-arg ref="jdbcTemplate" />
    </bean>

    <bean id="personDao" class="de.kreth.clubhelperbackend.dao.PersonDao">
        <property name="sqlDialect" ref="sqlForDialect" />
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>

    <bean id="dbcheckAspect" class="de.kreth.clubhelperbackend.aspects.MysqlDbCheckAspect">
        <constructor-arg ref="dataSource" />
    </bean>

<!--    <bean id="logger" class="de.kreth.clubhelperbackend.aspects.LoggerAspect" /> -->

    <aop:aspectj-autoproxy>
        <aop:include name="dbcheckAspect" />
<!--        <aop:include name="logger"/> -->
    </aop:aspectj-autoproxy>

</beans>

那么,一般来说,我怎样才能将 json 日期输出作为时间戳?

请注意,我不想更改数据类(getter),因为它们是从另一个项目生成的。

--- 编辑: 人物模型:

public class Person implements java.io.Serializable, Data  {

    private static final long serialVersionUID = -2810735258874241724L;
    private Long id;
    private String type;

    /** Not-null value. */
    private java.util.Date changed;
    /** Not-null value. */
    private java.util.Date created;

    public Person() {
    }

    public Person(Long id) {
        this.id = id;
    }

    public Person(Long id, String type,java.util.Date changed, java.util.Date created) {
        this.id = id;
        this.type = type;
        this.changed = changed;
        this.created = created;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    /** Not-null value. */
    public java.util.Date getChanged() {
        return changed;
    }

    /** Not-null value; ensure this value is available before it is saved to the database. */
    public void setChanged(java.util.Date changed) {
        this.changed = changed;
    }

    /** Not-null value. */
    public java.util.Date getCreated() {
        return created;
    }

    @Override
    public void setCreated(Date created) {
        this.created = created;
    }
}

日期界面:

package de.kreth.clubhelperbackend.pojo;
import java.util.Date;

public interface Data {
    public Long getId() ;
    public void setId(Long id);
    public Date getChanged();
    public void setChanged(Date changed);
    public Date getCreated();
    public void setCreated(Date created);
}

【问题讨论】:

  • 它如何知道日期所在的时区?
  • @SkinnyJ:我不明白你的问题。我认为 Unix 时间戳始终是 GMT。而且 Date 对象有本地时区,不需要 GregorianCalendar。
  • 请出示您的型号。通常你必须指定@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") Date dateField 才能得到这种风格的输出。
  • 我的观点是,yyyy-MM-dd 在逻辑上对于它所代表的时间点(如果有的话)是模棱两可的。将其转换为代表格林威治标准时间该日期午夜的日期需要做出很多假设。我不了解 Jackson,但对于任何想要将 LocalDate 表示为即时时间的人来说,这将是我的问题。
  • 我将数据和人员更改为使用日历而不是日期。然后输出是时间戳,但输入不再起作用,给出以下消息:服务器拒绝此请求,因为请求实体的格式不受所请求方法的请求资源支持。

标签: json spring maven spring-mvc jackson


【解决方案1】:

我认为 Jackson 对待 java.util.Datejava.sql.Date 的方式不同。尽管后者实际上是前者的子类,但杰克逊认为这两个类完全不同。

因此,如果您不希望将值转换为 'yyyy-MM-dd',请确保它不是 java.sql.Date 对象。

例如:

class Student {
   private java.util.Date birthDate;

   // getter and setter
}

Student san = new Student();

// Then JSON converted to: 'yyyy-MM-dd' format
san.setBirthDate(new java.sql.Date(System.currentTimeMillis()));

// Then JSON converted to: timestamp format or according to @JsonFormat format
san.setBirthDate(new java.util.Date());

【讨论】:

    【解决方案2】:

    According Jackson docs,Jackson 默认使用毫秒为单位的时间戳。

    所以我看到了两个选项。一个是您的日期格式由@beerbajay 在他的评论中提到的日期字段上的@JsonFormat 注释强制执行。

    第二个选项是有人为您的MappingJacksonHttpMessageConverter 配置了自定义ObjectMapper。此类示例配置位于this SO answer。我会尝试在您的应用程序中找到它,并与介绍它的队友讨论为什么需要它。

    如果没有配置这样的自定义ObjectMapper,那就奇怪了,但至少你可以尝试将SerializationConfig.getDateFormat显式配置为WRITE_DATES_AS_TIMESTAMPS为true。

    【讨论】:

    • 好吧,任何地方都没有@JsonFormat注解,也没有自定义ObjectMapper。作为我个人的TestProject,没有人可以问。我以前是通过eclipse的Spring MVC Project Wizard生成项目结构的。
    • Spring 4.1 btw Jackson 2.5.4 不知道 SerializationConfig.Feature WRITE_DATES_AS_TIMESTAMPS !?
    • JSonFormat 是杰克逊注解。您将需要 Jackson 依赖项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2013-03-18
    • 1970-01-01
    • 2023-03-17
    • 2021-04-19
    • 1970-01-01
    • 2018-09-01
    相关资源
    最近更新 更多