Spring Bootのコンテンツネゴシエーション入門:AcceptとContent-Typeの違いと使い方
生徒
「Spring BootでJSONとかXMLを切り替えて返すって、どうやってやるんですか?」
先生
「それはコンテンツネゴシエーションという仕組みを使うと簡単にできます。AcceptやContent-Typeというヘッダーがカギになりますよ」
生徒
「どっちも似てる気がするんですが、どう違うんですか?」
先生
「そこが大事なポイントです。では、Spring Bootのコンテンツネゴシエーションの基本から、両者の違い、設定方法、使い分けまで詳しく見ていきましょう!」
1. コンテンツネゴシエーションとは何か?
Spring Bootにおけるコンテンツネゴシエーションとは、クライアントの希望するレスポンス形式(たとえばJSONやXMLなど)に応じて、適切なフォーマットでデータを返す仕組みです。REST APIの開発では非常によく使われる機能です。
この仕組みにより、URLを変えることなく、ヘッダーの指定だけで出力形式を制御できます。
2. AcceptとContent-Typeの違い
HTTP通信では、AcceptとContent-Typeという2つの重要なヘッダーがあります。混同しやすいので、それぞれの役割を整理しましょう。
- Acceptヘッダー:クライアントが「どの形式のレスポンスが欲しいか」をサーバーに伝える。
- Content-Typeヘッダー:リクエストまたはレスポンスの「データの形式」を表す。
つまり、Acceptは要求(リクエスト)、Content-Typeは実際の中身(リクエストまたはレスポンス)の形式を表します。
3. Spring Bootのコンテンツネゴシエーションの動作
Spring Bootでは、Acceptヘッダーを見て、内部でHttpMessageConverterを使って適切な形式でレスポンスを返してくれます。特別な設定をしなくても、Jackson(JSON用)やJAXB(XML用)が組み込まれているため、簡単に切り替えが可能です。
@RestController
public class SampleController {
@GetMapping(value = "/data", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public SampleData getData() {
return new SampleData("ネコ", 3);
}
}
このようにproducesで複数の形式を指定することで、Acceptヘッダーの値に応じて自動的に出力形式が切り替わります。
4. AcceptヘッダーでJSONとXMLを切り替える
クライアントから送るAcceptヘッダーの例を見てみましょう。たとえば、curlでのリクエストは次のようになります。
curl -H "Accept: application/json" http://localhost:8080/data
curl -H "Accept: application/xml" http://localhost:8080/data
これにより、SampleDataクラスのインスタンスがJSONまたはXML形式で出力されます。とても柔軟な設計ですね。
5. Content-Typeでリクエストのデータ形式を指定する
Content-Typeは主にPOSTやPUTリクエストで、サーバーに送信するデータの形式を伝えるために使います。Spring Bootでは以下のように指定します。
@PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE)
public String createItem(@RequestBody Item item) {
return "登録完了";
}
この場合、Content-Type: application/jsonがリクエストに含まれていないと、415 Unsupported Media Typeエラーになります。
6. application.ymlやapplication.propertiesでデフォルト設定を変える
Spring Bootでは、コンテンツネゴシエーションの戦略をapplication.ymlまたはapplication.propertiesで変更できます。
spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.parameter-name=type
spring.mvc.contentnegotiation.favor-path-extension=false
spring.mvc.contentnegotiation.media-types.json=application/json
spring.mvc.contentnegotiation.media-types.xml=application/xml
これにより、?type=jsonなどのパラメータで出力形式を指定できるようになります。初心者にも扱いやすいオプションです。
7. パス拡張子による形式指定は非推奨
Spring Boot 2.6以降では、.jsonや.xmlなどの拡張子による出力指定はセキュリティ上の理由から非推奨となっています。代わりにAcceptヘッダーやクエリパラメータを使用しましょう。
これにより、予期しないファイル出力やルーティングの問題を防ぐことができます。
8. 独自フォーマットへの対応方法
もしJSONやXML以外のフォーマット(たとえばCSVや独自形式)を返したい場合は、独自のHttpMessageConverterを実装してWebMvcConfigurerに登録することで対応できます。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new CsvMessageConverter());
}
}
こうすることで、Accept: text/csvを受け取った場合にCSV出力ができるようになります。