Spring Boot 之使用 Json 详解

Spring Boot 之使用 Json 详解

简介 Spring Boot 支持的 Json 库

Spring Boot 支持三种 Json 库:

Gson

Jackson

JSON-B

Jackson 是 Spring Boot 官方推荐的默认库。

Spring Boot 提供了 Jackson 的自动配置,Jackson 是 spring-boot-starter-json 的一部分。当 Jackson 在类路径上时,会自动配置 ObjectMapper bean。

Spring Boot 提供了 Gson 的自动配置。当 Gson 在 classpath 上时,会自动配置 Gson bean。提供了几个 spring.gson.* 配置属性来自定义配置。为了获得更多控制,可以使用一个或多个 GsonBuilderCustomizer bean。

Spring Boot 提供了 JSON-B 的自动配置。当 JSON-B API 在 classpath 上时,将自动配置 Jsonb bean。首选的 JSON-B 实现是 Apache Johnzon,它提供了依赖关系管理。

Spring Web 中的序列化、反序列化

以下注解都是 spring-web 中提供的支持。

@ResponseBody

@Responsebody 注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 HTTP Response 对象的 body 数据区。一般在异步获取数据时使用。通常是在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上 @Responsebody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP 响应正文中。

示例:

@ResponseBody @RequestMapping(name = "/getInfo", method = RequestMethod.GET) public InfoDTO getInfo() { return new InfoDTO(); } @RequestBody

@RequestBody 注解用于读取 HTTP Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConverter 进行解析,然后把相应的数据绑定到要返回的对象上;再把 HttpMessageConverter 返回的对象数据绑定到 controller 中方法的参数上。

request 的 body 部分的数据编码格式由 header 部分的 Content-Type 指定。

示例:

@RequestMapping(name = "/postInfo", method = RequestMethod.POST) public void postInfo(@RequestBody InfoDTO infoDTO) { // ... } @RestController

Spring 4 以前:

如果需要返回到指定页面,则需要用 @Controller 配合视图解析器 InternalResourceViewResolver 。

如果需要返回 JSON,XML 或自定义 mediaType 内容到页面,则需要在对应的方法上加上 @ResponseBody 注解。

Spring 4 以后,新增了 @RestController 注解:

它相当于 @Controller + @RequestBody 。

如果使用 @RestController 注解 Controller,则 Controller 中的方法无法返回 jsp 页面,或者 html,配置的视图解析器 InternalResourceViewResolver 将不起作用,直接返回内容。

指定类的 Json 序列化、反序列化

如果使用 Jackson 序列化和反序列化 JSON 数据,您可能需要编写自己的 JsonSerializer 和 JsonDeserializer 类。自定义序列化程序通常通过模块向 Jackson 注册,但 Spring Boot 提供了另一种 @JsonComponent 注释,可以更容易地直接注册 Spring Beans。

您可以直接在 JsonSerializer 或 JsonDeserializer 实现上使用 @JsonComponent 注释。您还可以在包含序列化程序/反序列化程序作为内部类的类上使用它,如以下示例所示:

import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import org.springframework.boot.jackson.*; @JsonComponent public class Example { public static class Serializer extends JsonSerializer<SomeObject> { // ... } public static class Deserializer extends JsonDeserializer<SomeObject> { // ... } }

ApplicationContext 中的所有 @JsonComponent bean 都会自动注册到 Jackson。因为 @JsonComponent 是使用 @Component 进行元注释的,所以通常的组件扫描规则适用。

Spring Boot 还提供了 JsonObjectSerializer 和 JsonObjectDeserializer 基类,它们在序列化对象时提供了标准 Jackson 版本的有用替代方法。有关详细信息,请参阅 Javadoc 中的 JsonObjectSerializer 和 JsonObjectDeserializer。

@JsonTest

使用 @JsonTest 可以很方便的在 Spring Boot 中测试序列化、反序列化。

使用 @JsonTest 相当于使用以下自动配置:

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration

@JsonTest 使用示例:

想试试完整示例,可以参考:源码

@JsonTest @RunWith(SpringRunner.class) public class SimpleJsonTest { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private JacksonTester<InfoDTO> json; @Test public void testSerialize() throws Exception { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); InfoDTO infoDTO = new InfoDTO("JSON测试应用", "1.0.0", sdf.parse("2019-01-01 12:00:00")); JsonContent<InfoDTO> jsonContent = json.write(infoDTO); log.info("json content: {}", jsonContent.getJson()); // 或者使用基于JSON path的校验 assertThat(jsonContent).hasJsonPathStringValue("@.appName"); assertThat(jsonContent).extractingJsonPathStringValue("@.appName").isEqualTo("JSON测试应用"); assertThat(jsonContent).hasJsonPathStringValue("@.version"); assertThat(jsonContent).extractingJsonPathStringValue("@.version").isEqualTo("1.0.0"); assertThat(jsonContent).hasJsonPathStringValue("@.date"); assertThat(jsonContent).extractingJsonPathStringValue("@.date").isEqualTo("2019-01-01 12:00:00"); } @Test public void testDeserialize() throws Exception { String content = "{\"appName\":\"JSON测试应用\",\"version\":\"1.0.0\",\"date\":\"2019-01-01\"}"; InfoDTO actual = json.parseObject(content); assertThat(actual.getAppName()).isEqualTo("JSON测试应用"); assertThat(actual.getVersion()).isEqualTo("1.0.0"); } } Spring Boot 中的 json 配置 Jackson 配置

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppwfj.html