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 配置
当 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 详解的更多相关文章
- Spring Boot Actuator监控使用详解
在企业级应用中,学习了如何进行SpringBoot应用的功能开发,以及如何写单元测试.集成测试等还是不够的.在实际的软件开发中还需要:应用程序的监控和管理.SpringBoot的Actuator模块实 ...
- Spring Boot的启动器Starter详解
Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...
- Spring Boot(八):RabbitMQ详解
Spring Boot(八):RabbitMQ详解 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多 ...
- Spring boot注解(annotation)含义详解
Spring boot注解(annotation)含义详解 @Service用于标注业务层组件@Controller用于标注控制层组件(如struts中的action)@Repository用于标注数 ...
- Spring Boot中@ConditionalOnProperty使用详解
在Spring Boot的自动配置中经常看到@ConditionalOnProperty注解的使用,本篇文章带大家来了解一下该注解的功能. Spring Boot中的使用 在Spring Boot的源 ...
- Spring Boot启动命令参数详解及源码分析
使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...
- Spring Boot的SpringApplication类详解
相信使用过Spring Boot的开发人员,都对Spring Boot的核心模块中提供的SpringApplication类不陌生.SpringApplication类的run()方法往往在Sprin ...
- spring boot application properties配置详解
# =================================================================== # COMMON SPRING BOOT PROPERTIE ...
- spring boot application.properties 属性详解
2019年3月21日17:09:59 英文原版: https://docs.spring.io/spring-boot/docs/current/reference/html/common-appli ...
随机推荐
- socket通讯,TCP,UDP,HTTP的区别
socket编程有TCP和UDP, TCP:传送控制协议(Transmission Control Protocol) 传输控制协议TCP是TCP/IP协议栈中的传输层协议,它通过序列确认以及包重发机 ...
- (python)数据结构---集合
一.描述 set翻译为集合 set是可变的.无序的.不可重复的 set的元素要求可哈西(不可变的数据类型可哈西,可变的数据类型不可哈希) set是无序的,因此不可以索引,也不可以修改 线型结构的查询时 ...
- linux 环境变量设置
sudo gedit ~/.bashrc source ~/.bashrc
- 消除Warning: Using a password on the command line interface can be insecure的提示
最近在部署Zabbix时需要用脚本取得一些MySQL的返回参数,需要是numberic格式的,但是调用脚本时总是输出这一句: Warning: Using a password on the comm ...
- c/c++ 数组 数组的引用,指针数组的引用
c/c++ 数组 知识点 1,数组的声明和初始化,对应代码里的test1和test2 2,char数组,对应代码里的test3 3,数组不可以拷贝和复制,对应代码里的test4 4,指针数组, 数组的 ...
- Linux 系统出现电流音解决方案
迫于Windows 系统最近的各种故障,今天脱坑换了openSUSE Linux ,在上网途中播放视频时偶尔会出现电流音,虽然影响不大,但是还是进行了一些排查. 通过观察电流音出现时的系统负载的波段, ...
- JavaScript -- 时光流逝(十一):DOM -- Document 对象
JavaScript -- 知识点回顾篇(十一):DOM -- Document 对象 (1) document.activeElement: 返回文档中当前获得焦点的元素. <!doctype ...
- ELK-elkstack-使用消息队列
日志通过logstash收集到redis,之后从logstash从redis读取数据存入到ES 1. logstash使用redis测试 通过标准输入到redis中 logstash配置与启动 [yu ...
- SQLServer数据库增删改查
一.数据库定义 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库.数据库的操作分为两种形式:一种是直接在数据库管理工具图形化界面进行操作:一种是使用数据库脚本进行操作,数据库脚本可 ...
- Unity Shader 基础(4) 由深度纹理重建坐标
在PostImage中经常会用到物体本身的位置信息,但是Image Effect自身是不包含这些信息的,因为屏幕后处其实是使用特定的材质渲染一个刚好填满屏幕的四边形面片(四个角对应近剪裁面的四个角). ...