SpringMVC+GSON 对象序列化--日期格式的处理

Gson异常强大因此使用它代替了Jackson作为SpringMVC消息转换器。

在自己的项目中,发现对象在序列化后,日期格式出现了问题。

先看问题

在员工表中有一列是生日,字段类型为Date,也就是只存储到年月日,不带小时分秒,见下图数据库中的数据

前台列表向后台请求数据,然后在页面显示,可以看到,日期后面带有了小时分秒,而对于生日来说,这是没有意义的。见下图

问题出现在哪?

问题就出现在了 spring 的 message-converters 上,在我的项目中,配置的类型转换器为 google的 gson。可以看到全局配置为“yyyy-MM-dd HH:mm:ss:SSS” ,这是带有小时分秒的。所以当请求返回给浏览器的时候,spring会利用Gson将对象序列化输出到前端,按照配置的规则,就会带有小时分秒了。具体见下面的代码:

<!--开启 spring-mvc注解-->
<mvc:annotation-driven>
    <!--设置JSON转换器为Gson-->
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/plain;charset=UTF-8</value>
                    <value>text/html;charset=UTF-8</value>
                </list>
            </property>
        </bean>
        <bean class="org.springframework.http.converter.json.GsonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/plain;charset=UTF-8</value>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
            <property name="gson">
                <bean class="org.springframework.http.converter.json.GsonFactoryBean">
                    <property name="serializeNulls" value="true"/>
                    <property name="disableHtmlEscaping" value="true"/>
                    <property name="dateFormatPattern" value="yyyy-MM-dd HH:mm:ss:SSS" />
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

如何解决呢?

两种办法: 1、修改全局设置,将上述的配置修改yyyy-MM-dd。这样做有一个弊端:所有的日期处理都会受到影响。 2、利用@JsonAdapter注解,在想要特殊处理的属性上,添加该注解。

重点介绍第二种方式

首先,在要处理的属性上增加注解

@JsonAdapter(DateAdapter.class)
private Date birthday;

该注解接收一个参数,是类且继承TypeAdapter。要重写read(JsonReader in)、write(JsonWriter jsonWriter, Date date)这两个抽象方法。具体如下:

write是序列化、read是反序列化

package com.wt.common.core.adapter;

import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.bind.util.ISO8601Utils;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ProjectName: syInfo
 * @Package: com.wt.common.core.adapter
 * @Description: gson 日期适配器
 * @Author: lichking2017@aliyun.com
 * @CreateDate: 2018/5/5 上午11:12
 * @Version: v1.0
 */
public class DateAdapter extends TypeAdapter<Date>{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public void write(JsonWriter jsonWriter, Date date) throws IOException {
        jsonWriter.value(sdf.format(date));
    }

    @Override
    public Date read(JsonReader in) throws IOException {
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        } else {
            Date date = this.deserializeToDate(in.nextString());
            return date;
        }
    }

    private Date deserializeToDate(String s) {
        synchronized (sdf) {
            try {
                return sdf.parse(s);
            } catch (ParseException ignored) {}
            try {
                return sdf.parse(s);
            } catch (ParseException ignored) {}
            try {
                return ISO8601Utils.parse(s, new ParsePosition(0));
            } catch (ParseException e) {
                throw new JsonSyntaxException(s, e);
            }
        }
    }
}

OK!完事了,重启服务器查看效果

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java与Android技术栈

Retrofit 风格的 RxCache及其多种缓存替换算法

之前的文章《给 Java 和 Android 构建一个简单的响应式Local Cache》、《RxCache 整合 Android 的持久层框架 greenDA...

572
来自专栏JavaEdge

Bean Validation 介绍及最佳实践关于 Bean ValidationBean Validation 中的 constraint创建一个包含验证逻辑的简单应用(基于 JSP)定制化的 co

2937
来自专栏黑泽君的专栏

day33_Spring学习笔记_01

4 + 1:4个核心jar包(beans、core、context、expression)+ 1个依赖jar包(com.springsource.org.apa...

561
来自专栏pangguoming

SpringBoot实战 之 异常处理篇

在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,那该如何减少程序异常对用户体验的影...

3877
来自专栏逆向技术

内核开发知识第一讲.内核中的数据类型.重要数据结构.常用内核API函数.

  在内核中.程序的编写不能简单的用基本数据类型了. 因为操作系统不同.很有可能造成数据类型的长度不一.而产生重大问题.所以在内核中.

1352
来自专栏点滴积累

geotrellis使用(五)使用scala操作Accumulo

    要想搞明白Geotrellis的数据处理情况,首先要弄清楚数据的存放,Geotrellis将数据存放在Accumulo中。     Accumulo是一...

3634
来自专栏王磊的博客

Spring Boot(十二)单元测试JUnit

JUnit是一款优秀的开源Java单元测试框架,也是目前使用率最高最流行的测试框架,开发工具Eclipse和IDEA对JUnit都有很好的支持,JUnit主要用...

582
来自专栏JackieZheng

Nutch源码阅读进程4---parseSegment

前面依次看了nutch的准备工作inject和generate部分,抓取的fetch部分的代码,趁热打铁,我们下面来一睹parse即页面解析部分的代码,这块代码...

1907
来自专栏步履前行

Java 基础-LocalDate相关

那么在写具体的LocalDate前,我们先来看下为什么要在Java8中搞一套新的API呢,因为旧的Date类非常的难用,比如,其中的几个构造方法都被标注为@De...

2211
来自专栏个人分享

Netty的TCP粘包/拆包(源码二)

假设客户端分别发送了两个数据包D1和D2给服务器,由于服务器端一次读取到的字节数是不确定的,所以可能发生四种情况:

1454

扫码关注云+社区