从Spring Boot 2.2开始,Content-Type: application/json不再附带charset=UTF-8

总结

    • Spring Boot 2.2 から @RestController にて JSON を返す際の HTTP レスポンスヘッダで Content-Type: application/json になる (charset=UTF-8が付かない)

 

    Spring Boot 2.1 では @RestController にて JSON を返す際の HTTP レスポンスヘッダで Content-Type: application/json;charset=UTF-8 になる

验证代码

以下是我的应用程序的主要源代码:src/main/java/com/example/MyApp.java。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@SpringBootApplication
@RestController
public class MyApp {

  public static void main(String[] args) {
    SpringApplication.run(MyApp.class, args);
  }

  // Spring Boot 2.2 から Content-Type に charset=UTF-8 が付かない
  @GetMapping("/foo")
  public Map foo() {
    return Map.of("message", "こんにちわ、世界。");
  }

  // HTTP レスポンスヘッダを自前で指定することは可能
  @GetMapping("/bar")
  public ResponseEntity bar() {
    Map body = Map.of("message", "こんにちわ、世界。");
    // Content-Type: application/json;charset=UTF-8 を指定
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8));
    return new ResponseEntity<Map>(body, headers, HttpStatus.OK);
  }
}

使用Gradle构建脚本的Spring Boot 2.1

将文件名保存为2.1-build.gradle。

plugins {
  id 'org.springframework.boot' version '2.1.15.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'java'
}

group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
}

Spring Boot 2.2 的 Gradle 构建脚本

请将文件名保存为2.2-build.gradle。

plugins {
  id 'org.springframework.boot' version '2.2.8.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'java'
}

group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
}

验证

    実行環境: macOS Catalina + Java 11 (AdoptOpenJDK 11.0.7)

Spring Boot 2.1 春季启动框架版本2.1

使用Spring Boot 2.1构建和启动服务器。

$ gradle -b 2.1-build.gradle bootRun

用另一个控制台通过curl访问。
HTTP响应头中含有Content-Type: application/json;charset=UTF-8,并附带了charset=UTF-8。

$ curl --include http://localhost:8080/foo
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 16 Jun 2020 12:15:23 GMT

{"message":"こんにちわ、世界。"}
$ curl --include http://localhost:8080/bar
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 16 Jun 2020 12:15:27 GMT

{"message":"こんにちわ、世界。"}

Spring Boot 2.2
Spring Boot 2.2

使用Spring Boot 2.2构建并启动服务器。

$ gradle -b 2.2-build.gradle bootRun

从其他控制台使用curl进行访问。
HTTP响应头中包含Content-Type: application/json,而不附带charset=UTF-8。

$ curl --include http://localhost:8080/foo
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 16 Jun 2020 12:16:24 GMT

{"message":"こんにちわ、世界。"}

如果在自己的HTTP响应头中添加了charset=UTF-8,则会保留它。

$ curl --include http://localhost:8080/bar
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 16 Jun 2020 12:16:27 GMT

{"message":"こんにちわ、世界。"}

JSON的规范

JSON必须使用UTF-8进行编码。

最新的JSON规范「RFC 8259」和「ECMA-404第二版」已经发布。UTF-8编码是必需的。

在RFC 8259更新的JSON规范中,要求将UTF-8作为字符编码。

Content-Type 被指定为 application/json,但没有定义字符集。

RFC 8259:JavaScript对像记法(JSON)数据交换格式

JSON文本的媒体类型是application/json。

注意:此注册中没有定义”charset”参数。添加该参数对符合规范的接收方没有任何影响。

MediaType.APPLICATION_JSON_UTF8 不再被推荐使用

Spring Boot 2.1依赖的Spring Framework 5.1允许使用MediaType.APPLICATION_JSON_UTF8。

媒体类型(Spring Framework 5.1.16.RELEASE API)- Javadoc 日本語訳

public static final MediaType APPLICATION_JSON_UTF8
这是一个公共常量媒体类型,用于设置application/json;charset=UTF-8,该APPLICATION_JSON变量应用于JSON内容类型的设置。尽管在RFC7159中指定了“该注册未定义字符集参数”,但某些浏览器需要正确解释UTF-8特殊字符。

Spring Boot 2.2所依赖的Spring Framework 5.2版本已将MediaType.APPLICATION_JSON_UTF8标记为弃用(@Deprecated)。

媒体类型(Spring Framework 5.2.7.RELEASE API)- Javadoc 日本語翻訳

请勿使用 APPLICATION_JSON_UTF8。
像 Chrome 这样的主流浏览器在规范上符合要求,能够正确解释 UTF-8 的特殊字符,而无需 charset=UTF-8 参数。因此,我们建议在5.2版本中使用 APPLICATION_JSON。

废弃 MediaType.APPLICATION_JSON_UTF8,推荐使用 APPLICATION_JSON · Issue #22788 · spring-projects/spring-framework · GitHub

RFC 8259已经淘汰了RFC 7159,其中提到:“对于此注册,没有定义’charset’参数。为其添加参数对兼容的接收方没有任何影响。”(在第11节末尾)
…并且浏览器已经修复了它们的代码。

因此最好是明确文本并废弃这个常量。

看下列資料

    • Deprecate MediaType.APPLICATION_JSON_UTF8 in favor of APPLICATION_JSON · Issue #22788 · spring-projects/spring-framework · GitHub

 

    • Spring MVCのコントローラでの戻り値いろいろ – Qiita

 

    • Spring 5でレスポンスにヘッダを設定する方法

 

    • How to make spring boot default to application/json;charset=utf-8 instead of application/json;charset=iso-8859-1 – Stack Overflow

 

    • 438464 – json displayed with wrong encoding (i.e. not unicode) – chromium

 

    Media Types (Internet Assigned Numbers Authority)
广告
将在 10 秒后关闭
bannerAds