Java小强个人技术博客站点    手机版
当前位置: 首页 >> 开源 >> 关于SpringMVC返回JSON中时间对象序列化的问题

关于SpringMVC返回JSON中时间对象序列化的问题

10301 开源 | 2023-4-19

首先要说明一点,SpringMVC进行JSON序列化处理时,使用的工具包是Jackson

与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。

Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,当升级到 2.x 版本时,包名变为 com.fasterxml.jackson,本文讨论的内容是基于最新的 Jackson 的 2.9.1 版本。

Jackson 的核心模块由三部分组成。

jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

jackson-annotations,注解包,提供标准注解功能;

jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。


Jackson.jpg


当我们开发一个RestController接口时,如果返回的是对象,那么SpringMVC会进行JSON处理

表:

CREATE TABLE `sp_boot_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `u_name` varchar(255) CHARACTER SET latin1 DEFAULT '',
  `create_time` datetime DEFAULT NULL,
  `balance_point` decimal(10,0) DEFAULT NULL,
  `total_point` decimal(10,0) DEFAULT NULL,
  `address` varchar(255) CHARACTER SET latin1 DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `sp_boot_user` VALUES ('1', '1', '2023-04-19 22:02:02', '100', '100', '1');
INSERT INTO `sp_boot_user` VALUES ('2', '2', '2023-04-06 00:00:00', '50', '80', '2');

实体:

package com.example.springboot.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sp_boot_user")
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    @JsonSerialize(using = ToStringSerializer.class)
    private Integer id;
    @TableField(exist = false)
    private String ids;
    @TableField(value = "u_name")
    private String name;
    @TableField("create_time")
    private Date createTime;
    @TableField("balance_point")
    private Long balancePoint;
    @TableField("total_point")
    private Long totalPoint;
    @TableField(value = "address")
    private String address;
}

接口:

package com.example.springboot.controller;
import com.example.springboot.constant.DataResult;
import com.example.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test/mybatis")
public class MyBatisController {
    @Autowired
    private UserService userService;
    @RequestMapping("/user")
    public DataResult getUser(){
        return DataResult.success(userService.getById(1));
    }
}

请求:http://localhost:1088/test/mybatis/user  返回:

{
    "code": 0,
    "msg": "success",
    "data": {
        "id": "1",
        "ids": null,
        "name": "1",
        "createTime": "2023-04-19T14:02:02.000+00:00",
        "balancePoint": 100,
        "totalPoint": 100,
        "address": "1"
    },
    "success": true
}


我们看到返回的时间,格式不太友好,而且,显示的时间,不准确。

所以这里要说明一下的是,Jackson使用的时区,不是中国时区,因此需要手动指定下其使用的时区

Spring配置文件增加:

spring:
  jackson:
    default-property-inclusion: non_null # JSON处理时忽略非空字段
    time-zone: Asia/Shanghai             # 指定上海时区
    serialization:
      write-dates-as-timestamps: true

返回:

{
    "code": 0,
    "msg": "success",
    "data": {
        "id": "1",
        "name": "1",
        "createTime": 1681912922000,
        "balancePoint": 100,
        "totalPoint": 100,
        "address": "1"
    },
    "success": true
}

这个时间戳就是中国时间,但是有个问题,上面配置了写时间为时间戳,并没有格式化,修改Spring配置

spring:
  jackson:
    default-property-inclusion: non_null # JSON处理时忽略非空字段
    time-zone: Asia/Shanghai             # 指定上海时区
    date-format: yyyy-MM-dd HH:mm:ss
    serialization:
      write-dates-as-timestamps: false

返回:

{
    "code": 0,
    "msg": "success",
    "data": {
        "id": "1",
        "name": "1",
        "createTime": "2023-04-19 22:02:02",
        "balancePoint": 100,
        "totalPoint": 100,
        "address": "1"
    },
    "success": true
}


上面是一个全局配置,我们用可以单独配置某个字段的序列化方式

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sp_boot_user")
public class User {
    @TableField("create_time")
    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
}


如果我们要动态指定时区时,必须手动编码。

这里我们需要手动指定格式和时区,数据库默认是GMT+8,这里我们指定一个GMT+9来看效果。

@RequestMapping("/userStr")
public String getUserStr() throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setTimeZone(TimeZone.getTimeZone("GMT+9"));
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    return mapper.writeValueAsString(userService.getById(1));
}

返回

{
    "id": "1",
    "ids": null,
    "name": "1",
    "createTime": "2023-04-19 23:02:02",
    "balancePoint": 100,
    "totalPoint": 100,
    "address": "1"
}

我们看到格式是对的,时间也加了一个小时。


END

推荐您阅读更多有关于“ 时间 json springmvc 时区 gson ”的文章

上一篇:Redis客户端和插件 下一篇:Future机制实际应用

猜你喜欢

发表评论:

评论:

回复 Java小强 评论于 2023-04-19 09:49
当我们返回的是字符串,不是对象时,Spring的视图不会做任何处理。