在项目开拓中,接口与接口之间,前后端之间数据的传输都利用 Json 格式,在 Spring Boot 中,接口返回 Json 格式的数据很大略,在 Controller 中利用@RestController 表明即可。
@RestController 也是 Spring Boot 新增的一个表明,看一下该表明都包含什么。

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Controller@ResponseBodypublic @interface RestController { String value() default ""; }

可以看出, @RestController 表明包含了原来的 @Controller 和 @ResponseBody 注 解,@ResponseBody 表明是将返回的数据构造转换为 Json 格式。
以是在默认情形下,利用了 @RestController 表明即可将返回的数据构造转换成 Json 格式,Spring Boot 中默认利用的 Json 解析技能框架是 jackson。
pom.xml 中的 spring-boot-starter-web 依赖,可以看到一个 spring-boot-starter-json 依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>2.0.3.RELEASE</version><scope>compile</scope></dependency>

Spring Boot 中对依赖都做了很好的封装,可以看到很多 spring-boot-starter-xxx 系列的依赖,这是 Spring Boot 的特点之一,不须要人为去引入很多干系的依赖了,starter-xxx 系列直接都包含了所必要的依赖,以是再点spring-boot-starter-json 依赖,可以看到:

jsppost返回json数据格式SpringBoot返回Json NoSQL

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jdk8</artifactId><version>2.9.6</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.9.6</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-parameter-names</artifactId><version>2.9.6</version><scope>compile</scope></dependency>

到此为止,我们知道了 Spring Boot 中默认利用的 json 解析框架是 jackson。
下面我们 看一下默认的 jackson 框架对常用数据类型的转 Json 处理。

1. Spring Boot 默认对 Json 的处理

在实际项目中,常用的数据构造无非有类工具、List 工具、Map 工具,我们看一下默认 的 jackson 框架对这三个常用的数据构造转成 json 后的格式如何。

1.1 创建 User 实体类

为了测试,我们须要创建一个实体类,这里我们就用 User 来演示。

public class User { private Long id; private String username; private String password; / 省略 get、set 和带参布局方法 / } 1.2 创建 Controller 类

然后我们创建一个 Controller,分别返回User工具、List<User>和 Map<String,Oject>。

@RestController @RequestMapping("/json") public class JsonController { @RequestMapping("/user") public User getUser() { return new User(1, "Java码农", "123456"); } @RequestMapping("/list") public List getUserList() { List userList = new ArrayList<>(); User user1 = new User(1, "Java码农1", "123456"); User user2 = new User(2, "Java码农2", "123456"); userList.add(user1); userList.add(user2); return userList; } @RequestMapping("/map") public Map getMap() { Map map = new HashMap<>(3); User user = new User(1, "Java码农3", "123456"); map.put("作者信息", user); map.put("博客地址", "http://xxx.xx.com"); map.put("CSDN 地址", "http://xx.xxx.net/1"); map.put("粉丝数量", 4153); return map; } } 1.3 测试不同数据类型返回的 json

在浏览器中输入:localhost:8080/json/user 返回 json 如下:

{"id":1,"username":"Java码农","password":"123456"}

在浏览器中输入:localhost:8080/json/list 返回 json 如下:

[{"id":1,"username":"Java码农1 ","password":"123456"}, {"id":2,"username":"Java码农2 ","password":"123456"}]

在浏览器中输入:localhost:8080/json/map 返回 json 如下:

{"作者信息":{"id":1,"username":"Java码农3","password":"123456"}, "CSDN 地址 ":"http://xx.xxx.net/1","粉丝数量":4153,"博客地址 ":"http://xxx.xx.com"}

可以看出,map 中不管是什么数据类型,都可以转成相应的 json 格式,这样就非常方 便。

1.4 jackson 中对 null 的处理

在实际项目中,我们难免会碰着一些 null 值涌现,我们转 json 时,是不肯望有这些 null 涌现的,比如我们期望所有的 null 在转 json 时都变成 "" 这种空字符串,那怎么做呢?在 Spring Boot 中,我们做一下配置即可,新建一个 jackson 的配置类:

@Configurationpublic class JacksonConfig {@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {@Overridepublic void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeString("");}});return objectMapper;}}

然后我们修正一下上面返回 map 的接口,将几个值改成 null 测试一下:

@RequestMapping("/map") public Map getMap() { Map map = new HashMap<>(3); User user = new User(1, "Java码农3", null); map.put("作者信息", user); map.put("博客地址", "http://xxx.xx.com"); map.put("CSDN 地址", null); map.put("粉丝数量", 4153); return map; }

重启项目,再次输入:localhost:8080/json/map,可以看到 jackson 已经将所有 null 字段转成了空字符串了。

{"作者信息":{"id":1,"username":"Java码农3","password":""}, "CSDN 地址":"","粉 丝数量":4153,"博客地址":"http://xxx.xx.com"} 2. 利用阿里巴巴 FastJson 的设置2.1 fastJson 依赖导入

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.35</version></dependency> 2.2 利用 fastJson 处理 null

利用 fastJson 时,对 null 的处理和 jackson 有些不同,须要继续 WebMvcConfigurationSupport 类,然后覆盖 configureMessageConverters 方 法,在方法中,我们可以选择对要实现 null 转换的场景,配置好即可。
如下:

@Configuration public class fastJsonConfig extends WebMvcConfigurationSupport { / 利用阿里 FastJson 作为 JSON MessageConverter @param converters / @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures( // 保留 map 空的字段 SerializerFeature.WriteMapNullValue, // 将 String 类型的 null 转成"" SerializerFeature.WriteNullStringAsEmpty, // 将 Number 类型的 null 转成 0 SerializerFeature.WriteNullNumberAsZero, // 将 List 类型的 null 转成[] SerializerFeature.WriteNullListAsEmpty, // 将 Boolean 类型的 null 转成 false SerializerFeature.WriteNullBooleanAsFalse, // 避免循环引用 SerializerFeature.DisableCircularReferenceDetect); converter.setFastJsonConfig(config); converter.setDefaultCharset(Charset.forName("UTF-8")); List mediaTypeList = new ArrayList<>(); // 办理中文乱码问题,相称于在 Controller 上的@RequestMapping 中加 了个属性 produces = "application/json" mediaTypeList.add(MediaType.APPLICATION_JSON); converter.setSupportedMediaTypes(mediaTypeList); converters.add(converter); } }3. 封装统一返回的数据构造

以上是 Spring Boot 返回 json 的几个代表的例子,但是在实际项目中,除了要封装数据之外,我们每每须要在返回的 json 中添加一些其他信息,比如返回一些状态码 code ,返回一些 msg 给调用者,这样调用者可以根据 code 或者 msg 做一些逻辑判断。
以是在实际项目中,我们须要封装一个统一的 json 返回构造存储返复书息。

3.1 定义统一的 json 构造

由于封装的 json 数据的类型不愿定,以是在定义统一的 json 构造时,我们须要用到泛 型。
统一的 json 构造中属性包括数据、状态码、提示信息即可,布局方法可以根据实 际业务需求做相应的添加即可,一样平常来说,该当有默认的返回构造,也该当有用户指定 的返回构造。
如下:

public class JsonResult<T> {private T data;private String code;private String msg;/ 若没有数据返回,默认状态码为 0,提示信息为:操作成功!
/public JsonResult() {this.code = "0";this.msg = "操作成功!
";}/ 若没有数据返回,可以人为指定状态码和提示信息 @param code @param msg/public JsonResult(String code, String msg) {this.code = code;this.msg = msg;}/ 有数据返回时,状态码为 0,默认提示信息为:操作成功!
@param data/public JsonResult(T data) {this.data = data;this.code = "0";this.msg = "操作成功!
";}/ 有数据返回,状态码为 0,人为指定提示信息 @param data @param msg/public JsonResult(T data, String msg) {this.data = data;this.code = "0";this.msg = msg;}// 省略 get 和 set 方法}
3.2 修正 Controller 中的返回值类型及测试

由于 JsonResult 利用了泛型,以是所有的返回值类型都可以利用该统一构造,在详细的场景将泛型更换成详细的数据类型即可,非常方便,也便于掩护。
在实际项目中,还可以连续封装,比如状态码和提示信息可以定义一个列举类型,往后我们只须要掩护这个列举类型中的数据即可)。
根据以上的 JsonResult,我们改写一下 Controller,如下:

@RestController@RequestMapping("/jsonresult")public class JsonResultController {@RequestMapping("/user")public JsonResult<User> getUser() {User user = new User(1, "Java码农", "123456");return new JsonResult<>(user);}@RequestMapping("/list")public JsonResult<List> getUserList() {List<User> userList = new ArrayList<>();User user1 = new User(1, "Java码农1", "123456");User user2 = new User(2, "Java码农2", "123456");userList.add(user1);userList.add(user2);return new JsonResult<>(userList, "获取用户列表成功");}@RequestMapping("/map")public JsonResult<Map> getMap() {Map<String, Object> map = new HashMap<>(3);User user = new User(1, "Java码农3", null);map.put("作者信息", user);map.put("博客地址", "http://xxx.xx.com");map.put("CSDN 地址", null);map.put("粉丝数量", 4153);return new JsonResult<>(map);}}

我们重新在浏览器中输入:localhost:8080/jsonresult/user 返回 json 如下:

{"code":"0","data":{"id":1,"password":"123456","username":"Java码农 "},"msg":"操作成功!
"}

输入:localhost:8080/jsonresult/list,返回 json 如下:

{"code":"0","data":[{"id":1,"password":"123456","username":"Java码农1 "}, {"id":2,"password":"123456","username":"Java码农2"}],"msg":"获取用户列表 成功"}

输入:localhost:8080/jsonresult/map,返回 json 如下:

{"code":"0","data":{"作者信息":{"id":1,"password":"","username":"Java码农3 "}, "CSDN 地址":null,"粉丝数量":4153,"博客地址 ":"http://xxx.xx.com"},"msg":"操作成功!
"}

通过封装,我们不但将数据通过 json 传给前端或者其他接口,还带上了状态码和提示 信息,这在实际项目场景中运用非常广泛。

4、韶光格式问题

要求类型为:post,content-type=application/json, 后台用@RequestBody吸收,默认吸收及返回值格式为:yyyy-MM-dd HH:mm:ss。

办法一:application.propertities文件中配置:

# 格式化全局韶光字段spring.jackson.date-format=yyyy-MM-dd HH:mm:ss# 指定时间区域类型,Greenwich Mean Time (GMT) 格林尼治韶光,也叫做天下韶光。
spring.jackson.time-zone=GMT+8

个别韶光字段格式化可用表明:@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")

把稳:

1、支持(content-type=application/json)要求中格式为yyyy-MM-dd HH:mm:ss的字符串,后台用@RequestBody吸收,返回值date转为yyyy-MM-dd HH:mm:ss格式string;2、不支持(content-type=application/json)要求中yyyy-MM-dd等类型的字符串转为date;3、不支持java8日期api。

办法二:

// 自定义MappingJackson2HttpMessageConverter中objectMapper指定日期类型序列化即反序列化:@Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); // 忽略json字符串中不识别的属性 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略无法转换的工具 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // PrettyPrinter 格式化输出 objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); // NULL不参与序列化 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 指定时区 objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); // 日期类型字符串处理 objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // java8日期日期处理 JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); objectMapper.registerModule(javaTimeModule); converter.setObjectMapper(objectMapper); return converter; }

把稳:

1、支持(content-type=application/json)要求中格式为yyyy-MM-dd HH:mm:ss的字符串,后台用@RequestBody吸收,返回值date转为yyyy-MM-dd HH:mm:ss格式string;2、支持java8日期api。
3、不支持(content-type=application/json)要求中yyyy-MM-dd等类型的字符串转为date;

以上两种办法为json入参的全局化处理,推举利用办法二,尤其适宜大型项目在根本包中全局设置。

get要求及post表单日期韶光字符串格式转换

办法一:实现org.springframework.core.convert.converter.Converter,自定义参数转换器,如下:

@Componentpublic class DateConverter implements Converter<String, Date> { private static final String dateFormat = "yyyy-MM-dd HH:mm:ss"; @Override public Date convert(String value) { / 可对value进行正则匹配,支持日期、韶光等多种类型转换 @param value @return / SimpleDateFormat formatter = new SimpleDateFormat(dateFormat); try { return formatter.parse(value); } catch (Exception e) { throw new RuntimeException(String.format("parser %s to Date fail", value)); } }}

点评: 建议利用办法一时,对前端通报的string进行正则匹配,如yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、 HH:mm:ss等,进行匹配。
以适应多种场景。

办法二:利用spring自带表明@DateTimeFormat(pattern = "yyyy-MM-dd"),如下:

@DateTimeFormat(pattern = "yyyy-MM-dd")private Date startDate;

点评: 如果利用了办法一,spring会优先利用办法一进行处理,即办法二不生效。

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 入参:将前端传入字符串转为指定格式

@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") // 出参:将返回值转为指定格式

总结:

@JsonFormat:是一个韶光格式化表明,紧张用于前端与后端直接韶光格式的转换。
单独利用@JsonFormat表明时须要先通过@RequestBody将入参参数映射到实体后,@JsonFormat表明才能去对韶光格式进行约束;

1、可以约束韶光的吸收格式和相应格式 (吸收和相应的都是JSON字符串),将日期类型数据在JSON格式和java.util.Date工具之间转换。
与传输方向没有关系(前端到后端or后端到前端都可以利用);

2、它只会在类似@ResponseBody返回json数据的时候,才会返回格式化的yyyy-MM-dd HH:mm:ss韶光,直策应用System.out.println()输出的话,仍旧是类似“Fri Dec 01 21:05:20 CST 2017”这样的韶光样式。

3、若存储在mysql中的数据是date类型的,当我们读取出来封装在实体类中的时候,就会变成英文韶光格式,而不是yyyy-MM-dd HH:mm:ss这样的中文韶光,因此我们须要用到JsonFormat表明来格式化我们的韶光。

@DateTimeFormat:用于格式化前端传参日期后,通报给后端(哀求前端传参的格式);只能约束前台的韶光格式,必须与表明中的格式一样,否则报错。

1、紧张是前后端到后台的韶光格式的转换;可以吸收解析前端传入字符韶光数据;

2、只能约束前端入参韶光类型的格式,并不会修正原有的日期工具的格式,如果想要得到期望的日期格式,是须要自己手动转换的;

3、单独利用@DateTimeFormat 时,相应给前真个韶光会比实际韶光晚8个小时(时区缘故原由)

4、SpringBoot项目中单独利用@DateTimeFormat报错;缘故原由是springboot默认采取jackson,而jackson只能识别以下几种日期格式:"yyyy-MM-dd'T'HH:mm:ss.SSSZ"、"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"、"yyyy-MM-dd"、"EEE, dd MMM yyyy HH:mm:ss zzz"、long类型的韶光戳(毫秒韶光戳)

办理办法有以下几种:1.、采取long韶光戳,如:1537191968000;2、在传参的工具上加上@JsonFormat表明并且指定时区;3、利用指定格式 ;4、去掉@RequestBody表明。
5、采取全局处理办法统一处理,推举这个做法,重写springboot默认转换。

欢迎各位大佬指示。
喜好的朋友来个点赞+转发,感激~~~~