Spring Boot 之使用 Json 詳解

目錄css

Spring Boot 之使用 Json 詳解

簡介

Spring Boot 支持的 Json 庫

Spring Boot 支持三種 Json 庫:html

  • Gson
  • Jackson
  • JSON-B

Jackson 是 Spring Boot 官方推薦的默認庫。java

Spring Boot 提供了 Jackson 的自動配置,Jackson 是 spring-boot-starter-json 的一部分。當 Jackson 在類路徑上時,會自動配置 ObjectMapper bean。git

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,它提供了依賴關係管理。github

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

如下註解都是 spring-web 中提供的支持。web

@ResponseBody

@Responsebody 註解用於將 Controller 的方法返回的對象,經過適當的 HttpMessageConverter 轉換爲指定格式後,寫入到 HTTP Response 對象的 body 數據區。通常在異步獲取數據時使用。一般是在使用 @RequestMapping 後,返回值一般解析爲跳轉路徑,加上 @Responsebody 後返回結果不會被解析爲跳轉路徑,而是直接寫入 HTTP 響應正文中。spring

示例:json

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

@RequestBody

@RequestBody 註解用於讀取 HTTP Request 請求的 body 部分數據,使用系統默認配置的 HttpMessageConverter 進行解析,而後把相應的數據綁定到要返回的對象上;再把 HttpMessageConverter 返回的對象數據綁定到 controller 中方法的參數上。api

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); } // ... }

示例源碼

完整示例:源碼

引伸和引用

引伸

引用

相關文章
相關標籤/搜索