在日常开发中,我们都需要向页面传送json格式的字符串给页面进行渲染,怎么将对象序列化成json,我们只需要在对应方法头上加@ResponseBody注解或者直接在类上加@RestController注解,其实@RestController注解也就是@ResponseBody+@Controller的组合。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
} 那么在Spring Boot中默认的JSON解析方案是怎么样的?今天在看完视频学习后,顺便做一下笔记记录一下,方便以后查阅。
首先我们进行测试一下,创建User实体类:
/**
* @Author ChoiBin
* @Date 2019-07-28 14:27
* @Version 1.0
*/
public class User {
private Integer id;
private String username;
private String address;
//省略get set方法
} 创建一个UserController
package com.choi.json.controller;
import com.choi.json.bean.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* @Author ChoiBin
* @Date 2019-07-28 14:28
* @Version 1.0
*/
@RestController
public class UserController {
@GetMapping("/user")
public List<User> getUser(){
List<User> users = new ArrayList<>();
for(int i = 0;i < 10;i++){
User user = new User();
user.setId(i);
user.setUsername("choibin" + i);
user.setAddress("abc" + i);
users.add(user);
}
return users;
}
} 测试结果
在开发中,我们都需要将对象序列化成json字符串,也需要将json字符串反序列化成对象,其实在底层这两个过程都需要借助一个HttpMessageConverter对象,这是一个消息转换对象,主要有两方面的功能:
- 将服务端返回的对象序列化JSON字符串
- 将前端传来的JSON字符串反序列化成对象
Spring Boot中自动配置Jackson的类是
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration
@Configuration
class JacksonHttpMessageConvertersConfiguration {
JacksonHttpMessageConvertersConfiguration() {
}
//...还有其他方法
//当加入了JSON依赖以后,以下的配置就会生效,在序列化成JSON的过程,主要依赖的就是ObjectMapper对象
@Configuration
@ConditionalOnClass({ObjectMapper.class})
@ConditionalOnBean({ObjectMapper.class})
@ConditionalOnProperty(
name = {"spring.http.converters.preferred-json-mapper"},
havingValue = "jackson",
matchIfMissing = true
)
protected static class MappingJackson2HttpMessageConverterConfiguration {
protected MappingJackson2HttpMessageConverterConfiguration() {
}
//添加了JSON依赖后,默认会帮我们配置一个MappingJackson2HttpMessageConverter对象加入到容器当中,这个对象也就对象转换成JSON的工具类 @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);
}
}
} 而配置Gson的类是:org.springframework.boot.autoconfigure.http.GsonHttpMessageConvertersConfiguration。本文最主要的是JSON,所以就不贴源码了。
我们看了JSON的自动配置类,了解到转换过程是依赖于MappingJackson2HttpMessageConverter 这个对象,那么我们就使用一下,进行测试。
在User类中添加出生时间:
/**
* @Author ChoiBin
* @Date 2019-07-28 14:27
* @Version 1.0
*/
public class User {
private Integer id;
private String username;
private String address;
private Date birthDay;
} 测试结果
我们发现,最终显示的JSON中时间的格式不是我们想要的格式,这时我们在User类中的birthDay属性上加上@JsonFormat(pattern = "yyyy-MM-dd")
public class User {
private Integer id;
private String username;
private String address;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthDay;
} 重新测试
这种方法在类很多的时候,就需要很大的工作量,因此可以使用全局的方法,我们可以创建一个config类,重写mappingJackson2HttpMessageConverter方法,来进行实现,如下所示
/**
* @Author ChoiBin
* @Date 2019-07-28 15:08
* @Version 1.0
*/
@Configuration
public class WebMvcConfig {
@Bean
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper(); //主要是依赖于ObjectMapper来进行实现
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
return mappingJackson2HttpMessageConverter;
}
} 同样可以得到一样的结果
在源码中,ObjectMapper是通过参数创建来的,那这个参数又是从哪里来的?它来自于org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration这个类
@Configuration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
private static final Map<?, Boolean> FEATURE_DEFAULTS;
public JacksonAutoConfiguration() {
}
@Configuration
@ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
static class JacksonObjectMapperConfiguration {
JacksonObjectMapperConfiguration() {
}
@Bean
@Primary
@ConditionalOnMissingBean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.createXmlMapper(false).build();
}
}
} 如果我们没有实现ObjectMessage类,那么默认的就会使用这个;那么我们自定义一个ObjectMessage对象,也可以得到同样的结果。
public class WebMvcConfig {
// @Bean
// MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
// MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
// ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
// mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
// return mappingJackson2HttpMessageConverter;
// }
@Bean
ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));
return objectMapper;
}
} 通过这个例子的实现,自己也是明白了Spring Boot中JSON配置的原理,如果自己没有实现对应的方法,那么就会使用Spring Boot中默认的。通过重写相应方法,我们就可以满足自己需求。

京公网安备 11010502036488号