我们知道所有JSON数据的生成都离不开HttpMessageConverter,HttpMessageConverter这是一个消息转换工具,主要有两方面的功能:
1、将服务端返回的对象序列化成JSON字符串
2、将前端传来的JSON字符串反序列化成Java对象
在springmvc中也是自动帮我们配置了Jackson和Gson的HttpMessageConverter,在springboot中又对这两个做了自动化配置,一个是JacksonHttpMessageConvertersConfiguration,一个是GsonHttpMessageConvertersConfiguration
我们要是使用jackson和gson的话,没有额外的配置,只需要添加依赖即可
JacksonHttpMessageConvertersConfiguration源码
@Configuration
class JacksonHttpMessageConvertersConfiguration {
JacksonHttpMessageConvertersConfiguration() {
}
@Configuration
@ConditionalOnClass({XmlMapper.class})
@ConditionalOnBean({Jackson2ObjectMapperBuilder.class})
protected static class MappingJackson2XmlHttpMessageConverterConfiguration {
protected MappingJackson2XmlHttpMessageConverterConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter(Jackson2ObjectMapperBuilder builder) {
return new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build());
}
}
//配置类注解
@Configuration
//条件注解,主要导入ObjectMapper相关依赖,后面的配置就会生效
@ConditionalOnClass({ObjectMapper.class})
@ConditionalOnBean({ObjectMapper.class})
@ConditionalOnProperty(
name = {"spring.http.converters.preferred-json-mapper"},
havingValue = "jackson",
matchIfMissing = true
)
//主要是这个类
protected static class MappingJackson2HttpMessageConverterConfiguration {
protected MappingJackson2HttpMessageConverterConfiguration() {
}
//如果我们配置了MappingJackson2HttpMessageConverter就按照我们配置的来,没有配置就按照它这个配置来,默认帮我们生成
@Bean
@ConditionalOnMissingBean(
value = {MappingJackson2HttpMessageConverter.class},
ignoredType = {"org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter", "org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter"}
)
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
return new MappingJackson2HttpMessageConverter(objectMapper);
}
}
以上只要我们定义一个配置类,定义MappingJackson2HttpMessageConverter实例,定义我们自己的格式,比如说对日期的处理等
GsonHttpMessageConvertersConfiguration源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.http;
import com.google.gson.Gson;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@Configuration
@ConditionalOnClass({Gson.class})
class GsonHttpMessageConvertersConfiguration {
GsonHttpMessageConvertersConfiguration() {
}
private static class JacksonAndJsonbUnavailableCondition extends NoneNestedConditions {
JacksonAndJsonbUnavailableCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty(
name = {"spring.http.converters.preferred-json-mapper"},
havingValue = "jsonb"
)
static class JsonbPreferred {
JsonbPreferred() {
}
}
@ConditionalOnBean({MappingJackson2HttpMessageConverter.class})
static class JacksonAvailable {
JacksonAvailable() {
}
}
}
private static class PreferGsonOrJacksonAndJsonbUnavailableCondition extends AnyNestedCondition {
PreferGsonOrJacksonAndJsonbUnavailableCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@Conditional({GsonHttpMessageConvertersConfiguration.JacksonAndJsonbUnavailableCondition.class})
static class JacksonJsonbUnavailable {
JacksonJsonbUnavailable() {
}
}
@ConditionalOnProperty(
name = {"spring.http.converters.preferred-json-mapper"},
havingValue = "gson"
)
static class GsonPreferred {
GsonPreferred() {
}
}
}
@Configuration
@ConditionalOnBean({Gson.class})
@Conditional({GsonHttpMessageConvertersConfiguration.PreferGsonOrJacksonAndJsonbUnavailableCondition.class})
protected static class GsonHttpMessageConverterConfiguration {
protected GsonHttpMessageConverterConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public GsonHttpMessageConverter gsonHttpMessageConverter(Gson gson) {
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
converter.setGson(gson);
return converter;
}
}
}
和JacksonHttpMessageConvertersConfiguration 也是差不多的,这里不做过多介绍
下面我们来看看json的解析是如何实现的
定义User类
package com.zhouym.jsondemo;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
/**
* 〈User类〉
*
* @author zhouym
* @create 2019/8/7
* @since 1.0.0
*/
public class User {
private Integer id;
private String name;
private String address;
@JsonFormat(pattern = "yyyy/MM/dd")
private Date date;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
", date=" + date +
'}';
}
}
通过上面的JsonFormat注解也是可以实现对日期的格式化,但是如果一个类中有多个,就需要配置多个注解,显然不利于维护,下面我们创建controller类
package com.zhouym.jsondemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/7
* @since 1.0.0
*/
@RestController
public class HelloController {
@GetMapping("/query")
public List<User> query(){
List<User> list = new ArrayList<>();
for (int i=0;i < 10;i++){
User user = new User();
user.setId(i);
user.setName("zhangsan--"+i);
user.setAddress("sz---"+i);
user.setDate(new Date());
list.add(user);
}
return list;
}
}
启动服务器,我们来看看页面输出
我们再来使用配置类定义的格式看看
package com.zhouym.jsondemo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.text.SimpleDateFormat;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/7
* @since 1.0.0
*/
@Configuration
public class WebMvcConfig{
@Bean
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper om = new ObjectMapper();
om.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
converter.setObjectMapper(om);
return converter;
}
但是发现没有在配置类中,ObjectMapper才是核心的格式转化,我们只需要构建ObjectMapper实例来看看能否实现
package com.zhouym.jsondemo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.text.SimpleDateFormat;
/**
* 〈〉
*
* @author zhouym
* @create 2019/8/7
* @since 1.0.0
*/
@Configuration
public class WebMvcConfig{
// @Bean
// MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
// MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// ObjectMapper om = new ObjectMapper();
// om.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
// converter.setObjectMapper(om);
// return converter;
// }
@Bean
ObjectMapper objectMapper(){
ObjectMapper om = new ObjectMapper();
om.setDateFormat(new SimpleDateFormat("yyyy年MM月dd日"));
return om;
}
}