Jackson的使用和定制
springmvc在使用注解@ResponseBody返回一个POJO对象时, 其内部会借助Jackson来完成POJO转化为JSON的工作.
public class Message {
private String userId; // 用户id
private String message; // 消息实体
private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
private String extra; // 额外附带信息
}
其最终讲转换为如下的json格式:

如果开发者需要如下需求:
1). json实体的key命名规则, 全小写化, 不同单词以"_"字符连接.
2). 返回时间字段, 需满足"yyyy-MM-dd HH:mm:ss"格式
3). 省略掉extra字段
由此可见我们的最终目标是:
{"user_id":"1001","message":"message","timestamp":"2015-08-31 12:16:30"}
解决篇:
• 重命名
jackson对重命名的处理, 引入注解JsonProperty来实现. 其对单个属性配置有效.
@JsonProperty(value="user_id")
private String userId; // 用户id
注: value属性设置为用户想要的命名即可.
当然还有另一种方式注解方式, 是JsonNaming, 其修饰于POJO类上. 用于对所有属性, 进行统一的命名转换.
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class Message {
...
}
注: PropertyNamingStrategy就非常漂亮地把所有的类属性名称都转换为小写, 同时单词(驼峰命令法)之间使用'_'字符来分割.
自定义的Strategy类, 需要实现如下抽象类:
public abstract class PropertyNamingStrategy implements Serializable {
public abstract static class PropertyNamingStrategyBase extends PropertyNamingStrategy {
public abstract String translate(String var1);
}
}
• 字段可见性
过滤某些字段属性, jackson引入了注解JsonIgnore. 其对单个属性生效.
@JsonIgnore
private String extra; // 额外附带信息
还有另外一种方式, 是采用JsonIgnoreProperties, 其修饰POJO类, 指定一组需要忽略的字段.
// *) 字典{}内是property name列表
@JsonIgnoreProperties({"extra", "extra1", "extra2"})
public class Message {
...
}
• 自定义序列化/反序列化
jackson采用@JsonSerialize和@JsonDeserialize来实现自定义序列化/反序列化的实现. 如之前的时间字段作为例子.
定义时间序列化的实现类.
public class Message {
@JsonSerialize(using=DemoDateSerializer.class)
@JsonDeserialize(using=DemoDateDeserializer.class)
private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
}
// *) JSON的序列化类
class DemoDateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
jgen.writeString(dateFormat.format(value));
}
}
// *) JSON的反序列化类
class DemoDateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jp, DeserializationContext dctx) throws IOException, JsonProcessingException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return dateFormat.parse(jp.getValueAsString());
} catch (ParseException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
除了常规的时间格式转换, 还能正则提取等功能. 序列化和反序列化的自定义, 使得Jackson更加的强大. 犹如hive中的UDF函数.
最终的定义的类修改如下:
public class Message {
@JsonProperty(value="user_id")
private String userId; // 用户id
private String message; // 消息实体
@JsonSerialize(using=DemoDateSerializer.class)
@JsonDeserialize(using=DemoDateDeserializer.class)
private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
@JsonIgnore
private String extra; // 额外附带信息
}
@DateTimeFormat 和 @JsonFormat 注解
定义一个pojo,它有一个 java.util.Date 类型的属性 date。
import java.util.Date;
public class DateVo {
private Date date;
public void setDate(Date date){
this.date = date;
}
public Date getDate(){
return date;
}
}
定义一个Controller
@RestController
@RequestMapping("/date/")
public class DateController { @RequestMapping("test")
public DateVo getDate(DateVo vo){
System.out.println("date1:"+vo.getDate()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(vo.getDate());
System.out.println("date2:"+date); DateVo vo2 = new DateVo();
vo2.setDate(new Date());
return vo2;
}
}
访问 /date/test ,并传入参数:2018-08-02 22:05:55
发现并不能访问成功,会抛出异常:

2. 入参格式化
这时,就可以使用 Spring 的 @DateTimeFormat 注解格式化参数,来解决上述问题。
public class DateVo {
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date date;
public void setDate(Date date){
this.date = date;
}
public Date getDate(){
return date;
}
}
再像上面一样访问 /date/test ,并传入参数:2018-08-02 22:05:55,将在控制台上打印:
date1:Thu Aug 02 22:05:55 CST 2018
date2:2018-08-02 22:05:55
可以看到,加入 @DateTimeFormat 注解后参数可以被接收到了,但日期时间的格式还是需要自己再手动转换一下。
因为 @DateTimeFormat 注解的 pattern 属性值指定的日期时间格式并不是将要转换成的日期格式,这个指定的格式是和传入的参数对应的,假如注解为:
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss")则传入的参数应该是这样的:2018/08/02 22:05:55
3. 出参格式化
在上述示例中,调用接口的返回结果为:
"date": "2018-08-01T14:25:31.296+0000"
这个格式并不是我们想要的,那么如何将其进行格式化?这时就需要用到 jackson 的 @JsonFormat 注解。
public class DateVo {
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss"
)
private Date date;
public void setDate(Date date){
this.date = date;
}
public Date getDate(){
return date;
}
}
继续访问 /date/test ,并传入参数:2018-08-02 22:05:55,可以看到接口返回的结果为:
"date": "2018-08-01 14:32:57"
虽然时间格式正确了,但实际上当前时间是 “2018-08-01 22:32:57” ,早了8个小时。因为,jackson在序列化时间时是按照国际标准时间GMT进行格式化的,而在国内默认时区使用的是CST时区,两者相差8小时。
所以,@JsonFormat 注解还要再加一个属性:
@JsonFormat(
pattern = "yyyy-MM-dd HH:mm:ss",
timezone = "GMT+8"
)
private Date date;
这样,结果就正确了。
@JsonInclude(JsonInclude.Include.NON_NULL)标签去除json数据中的空值问题
@JsonInclude(JsonInclude.Include.NON_NULL)标记是jackson包提供的json序列化方法,已经集成于Springboot2.0中,此方法的配置意在可以对实体json序列化的时候进行对应的数值处理,
将该标记放在属性上,如果该属性为NULL则不参与序列化
如果放在类上边,那对这个类的全部属性起作用
Include.Include.ALWAYS 默认
Include.NON_DEFAULT 属性为默认值不序列化
Include.NON_EMPTY 属性为 空(“”) 或者为 NULL 都不序列化
Include.NON_NULL 属性为NULL 不序列化
Jackson的使用和定制的更多相关文章
- spring学习笔记---Jackson的使用和定制
前言: JAVA总是把实体对象(数据库/Nosql等)转换为POJO对象再处理, 虽然有各类框架予以强力支持. 但实体对象和POJO, 由于"饮食习惯", "民族特色 ...
- springmvc学习笔记--REST API的异常处理
前言: 最近使用springmvc写了不少rest api, 觉得真是一个好框架. 之前描述的几篇关于rest api的文章, 其实还是不够完善. 比如当遇到参数缺失, 类型不匹配的情况时, 直接抛出 ...
- spring学习笔记---第三方SDK(Rest API)和Jaskson的巧用
前言: 其实我以前一直不懂电商, 以及电商中所涉及的业务概念. 对于SKU等名词, 觉得有些玄乎. 对其背后的数据模型, 也有莫名的未知恐惧感: 庞大而理不清头绪. 不过最近有机会接触了微商(有赞), ...
- SpringMVC请求参数接收总结
前提 在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结.SpringMVC中处理控制器参数的接口是HandlerMethodArgumentRes ...
- SpringMVC请求参数接收总结(一)
前提 在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结.SpringMVC中处理控制器参数的接口是HandlerMethodArgumentRes ...
- SpringMVC请求参数总结
前提 在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结.SpringMVC中处理控制器参数的接口是HandlerMethodArgumentRes ...
- 2.5万字长文简单总结SpringMVC请求参数接收
这是公众号<Throwable文摘>发布的第22篇原创文章,暂时收录于专辑<架构与实战>.暂定下一篇发布的长文是<图文分析JUC同步器框架>,下一篇发布的短文是&l ...
- spring boot定制Jackson ObjectMapper,为什么不生效
先说结论: 项目中定制了spring 的redisTemplate,而这个template没有使用我自定义的Jackson ObjectMapper.所以不生效. 下面是详细过程: 起因是spring ...
- 【私人定制jackson】定制jackson的自定义序列化(null值的处理)
最近用springMVC做服务端的http+json的接口,出现一个不是特别容易解决的问题: 在对List类型的值进行处理时,有一部分服务是有做一些逻辑判断的,在逻辑判断不通过的时候会返回一个null ...
随机推荐
- python 函数定义自变量的写法及调用
import pandas as pd #函数定义时指明自变量,指明自变量的类型,指定自变量的默认值 #函数定义时,可以通过"自变量名称=常量"的方式指定自变量的默认值,调用时可以 ...
- 家庭账本开发day06
编写查询页面,学习layUI的动态表格使用,绑定数据源, table.render({ elem: '#currentTableId', url: '../ ...
- Java基础00-多态19
1. 多态 多态 1.1 多态概述 代码示例: 动物类: public class Animal { public void eat(){ System.out.println("动物吃东西 ...
- Appium - adb monkey参数(三)
monkey 参数 1.常规类参数 A.帮助类参数 monkey -h B.日志级别 $ adb shell monkey -v <event-count> . 2.事件类参数 A .执 ...
- 【洛谷P1816 忠诚】线段树
题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了 ...
- 第二十一篇 -- QTimer实现秒表功能
效果图: 程序一开始就开始计时,当完成了相关功能(在线程中完成)之后,就触发停止信号,停止定时器. time.py #!/usr/bin/env python # _*_ coding: UTF-8 ...
- 深入刨析tomcat 之---第14篇 对应19章,使用manager管理 web应用
writedby 张艳涛 第19章讲的是管理程序,当一个tomcat启动的时候,能通过远程浏览器能访问tomcat,启动web应用,关闭web应用,查看web应用 怎么实现的呢? 在webapp 文件 ...
- 在 CentOS 7.5 64位上使用 yum 安装 MySQL 8.0
前段时间在 CentOS 7.5 64位上安装 MySQL 8.0.查了些资料,在这里记录一下详细的安装和设置步骤. 一.安装 使用yum安装MySQL之前需要先下载对应的.rpm文件,下载方法: 去 ...
- 从零开始了解kubernetes
kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群.滚动升级回滚.弹性伸缩.自动治愈.服务发现等多种特性能力. 本文将带着大家快速了解 kubernetes , ...
- MySQL隔离级别的实现
虽然平时已经很少使用MySQL了,但是数据库作为基本技能仍然不能忘,最近在学习数据库隔离级别,在此写下个人理解以备复习. 大家都知道数据库事务ACID(原子性.一致性.隔离性和持久性)的四个特征,也知 ...