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 数据,您可能需要编写自己的 JsonSerializerJsonDeserializer 类。自定义序列化程序通常通过模块向 Jackson 注册,但 Spring Boot 提供了另一种 @JsonComponent 注释,可以更容易地直接注册 Spring Beans。

您可以直接在 JsonSerializerJsonDeserializer 实现上使用 @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 还提供了 JsonObjectSerializerJsonObjectDeserializer 基类,它们在序列化对象时提供了标准 Jackson 版本的有用替代方法。有关详细信息,请参阅 Javadoc 中的 JsonObjectSerializerJsonObjectDeserializer

@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 配置

当 Spring Boot 的 json 库为 jackson 时,可以使用以下配置属性(对应 JacksonProperties 类):

spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance, `yyyy-MM-dd HH:mm:ss`.
spring.jackson.default-property-inclusion= # Controls the inclusion of properties during serialization. Configured with one of the values in Jackson's JsonInclude.Include enumeration.
spring.jackson.deserialization.*= # Jackson on/off features that affect the way Java objects are deserialized.
spring.jackson.generator.*= # Jackson on/off features for generators.
spring.jackson.joda-date-time-format= # Joda date time format string. If not configured, "date-format" is used as a fallback if it is configured with a format string.
spring.jackson.locale= # Locale used for formatting.
spring.jackson.mapper.*= # Jackson general purpose on/off features.
spring.jackson.parser.*= # Jackson on/off features for parsers.
spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy. Can also be a fully-qualified class name of a PropertyNamingStrategy subclass.
spring.jackson.serialization.*= # Jackson on/off features that affect the way Java objects are serialized.
spring.jackson.time-zone= # Time zone used when formatting dates. For instance, "America/Los_Angeles" or "GMT+10".
spring.jackson.visibility.*= # Jackson visibility thresholds that can be used to limit which methods (and fields) are auto-detected.

GSON 配置

当 Spring Boot 的 json 库为 gson 时,可以使用以下配置属性(对应 GsonProperties 类):

spring.gson.date-format= # Format to use when serializing Date objects.
spring.gson.disable-html-escaping= # Whether to disable the escaping of HTML characters such as '<', '>', etc.
spring.gson.disable-inner-class-serialization= # Whether to exclude inner classes during serialization.
spring.gson.enable-complex-map-key-serialization= # Whether to enable serialization of complex map keys (i.e. non-primitives).
spring.gson.exclude-fields-without-expose-annotation= # Whether to exclude all fields from consideration for serialization or deserialization that do not have the "Expose" annotation.
spring.gson.field-naming-policy= # Naming policy that should be applied to an object's field during serialization and deserialization.
spring.gson.generate-non-executable-json= # Whether to generate non executable JSON by prefixing the output with some special text.
spring.gson.lenient= # Whether to be lenient about parsing JSON that doesn't conform to RFC 4627.
spring.gson.long-serialization-policy= # Serialization policy for Long and long types.
spring.gson.pretty-printing= # Whether to output serialized JSON that fits in a page for pretty printing.
spring.gson.serialize-nulls= # Whether to serialize null fields.

Spring Boot 中使用 Fastjson

国内很多的 Java 程序员更喜欢使用阿里的 fastjson 作为 json lib。那么,如何在 Spring Boot 中将其替换默认的 jackson 库呢?

你需要做如下处理:

(1)引入 fastjson jar 包:

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>

(2)实现 WebMvcConfigurer 接口,自定义 configureMessageConverters 接口。如下所示:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer { private final Logger log = LoggerFactory.getLogger(this.getClass()); /**
* 自定义消息转换器
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 清除默认 Json 转换器
converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); // 配置 FastJson
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString,
SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.DisableCircularReferenceDetect); // 添加 FastJsonHttpMessageConverter
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
fastJsonHttpMessageConverter.setFastJsonConfig(config);
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(fastJsonHttpMessageConverter); // 添加 StringHttpMessageConverter,解决中文乱码问题
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
converters.add(stringHttpMessageConverter);
} // ...
}

示例源码

完整示例:源码

引申和引用

引申

引用

Spring Boot 之使用 Json 详解的更多相关文章

  1. Spring Boot Actuator监控使用详解

    在企业级应用中,学习了如何进行SpringBoot应用的功能开发,以及如何写单元测试.集成测试等还是不够的.在实际的软件开发中还需要:应用程序的监控和管理.SpringBoot的Actuator模块实 ...

  2. Spring Boot的启动器Starter详解

    Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...

  3. Spring Boot(八):RabbitMQ详解

    Spring Boot(八):RabbitMQ详解 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多 ...

  4. Spring boot注解(annotation)含义详解

    Spring boot注解(annotation)含义详解 @Service用于标注业务层组件@Controller用于标注控制层组件(如struts中的action)@Repository用于标注数 ...

  5. Spring Boot中@ConditionalOnProperty使用详解

    在Spring Boot的自动配置中经常看到@ConditionalOnProperty注解的使用,本篇文章带大家来了解一下该注解的功能. Spring Boot中的使用 在Spring Boot的源 ...

  6. Spring Boot启动命令参数详解及源码分析

    使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...

  7. Spring Boot的SpringApplication类详解

    相信使用过Spring Boot的开发人员,都对Spring Boot的核心模块中提供的SpringApplication类不陌生.SpringApplication类的run()方法往往在Sprin ...

  8. spring boot application properties配置详解

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  9. spring boot application.properties 属性详解

    2019年3月21日17:09:59 英文原版: https://docs.spring.io/spring-boot/docs/current/reference/html/common-appli ...

随机推荐

  1. Deep Learning - 1 神经网络

    Artificial Neuron 人工神经元有: Perceptrons(感知机) Sigmoid Perceptron 感知机input是多个二进制,output是一个二进制. graph LR ...

  2. (后端)Mybatis实现批量删除操作(转)

    原文地址:https://blog.csdn.net/javaee_sunny/article/details/52511842 一. 这里主要考虑两种参数类型:数组或者集合. 而这点区别主要体现在E ...

  3. Linux 中提高的 SSH 的安全性

    SSH 是远程登录 Linux 服务器的最常见的方式.且 SSH 登录的时候要验证的,相对来讲会比较安全.那只是相对,下面会介绍一些方式提高 SSH 的安全性 SSH 的验证 而SSH 登录时有两种验 ...

  4. Python GUI编程实例

    import os from time import sleep from tkinter import * from tkinter.messagebox import showinfo class ...

  5. Spark性能优化【OOM】

    一.异常情况 Spark on yarn模式下,当yarn为client的模式时没有OOM而cluster模式下出现OOM 二.异常分析 由于client模型没有出现OOM而cluster模式出现OO ...

  6. java----鲁棒性

    所谓“鲁棒性”,是指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性. Java鲁棒性的特点如下: Java在编译和运行程序时都要对可能出现的问题进行检查,以防止错误的产生. Java ...

  7. [20181225]12CR2 SQL Plan Directives.txt

    [20181225]12CR2 SQL Plan Directives.txt --//12C引入SQL PLAN Directives.12cR1版本会造成大量的动态取样,影响性能.许多人把OPTI ...

  8. mssql sqlserver in 关键字在值为null的应用举例

    转自:http://www.maomao365.com/?p=6873 摘要: 下文通过案例分析in 关键字在值为null的应用举例, 分析出not in关键字在null值产生的异常信息 如下所示: ...

  9. LINQ的求和 平均 最大 最小 分组 计数 等等

    1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述:使用Group By按Categ ...

  10. python库安装方法及下载依赖库

    python库的安装方法 直接使用pip pip install xxx python第三方下载,可以在地址栏上输入所需库的名字,进行快速查找 源码安装 python setup.py install ...