JSONレスポンスのカスタマイズ(@ResponseBody)をやさしく解説!Spring初心者向け完全ガイド
新人
「SpringでAPIを作っているんですが、画面にJSONが表示されるのはなぜですか?」
先輩
「それは、@ResponseBodyというアノテーションのおかげで、JavaオブジェクトがJSONに変換されて返されているからなんだ。」
新人
「えっ?ビューとかHTMLを返すのとどう違うんですか?」
先輩
「それじゃあ今回は、@ResponseBodyとJSONレスポンスの仕組みについて、やさしく解説していこう!」
1. @ResponseBodyとは何か?
Spring MVCでは、通常@Controllerを使うと、メソッドの戻り値はHTMLテンプレートなどのビュー名として解釈されます。しかし、@ResponseBodyアノテーションを付けることで、その戻り値は画面に直接「文字列」や「JSON形式のデータ」として返されるようになります。
つまり、@ResponseBodyを使うと、JavaのオブジェクトをJSONレスポンスとしてブラウザやクライアントに返すことができます。
実際の使い方は以下のようになります。
@Controller
public class SampleController {
@ResponseBody
@RequestMapping("/hello")
public String helloMessage() {
return "こんにちは、JSONレスポンス!";
}
}
上記のコードでは、ビューを返さずに直接文字列がブラウザに表示されます。これはHTMLではなく、純粋な文字レスポンスです。さらにJSON形式でデータを返す場合は、Javaのクラス(DTO)を返すことで自動的にJSONに変換されます。
2. JSONレスポンスの仕組み(内部で何が行われているか)
Springで@ResponseBodyを使用すると、Javaのオブジェクトが自動的に「JSON形式」にシリアライズされてレスポンスとして返されます。この変換処理は、内部的にはHttpMessageConverterという仕組みが担当しています。
代表的な変換ライブラリとしてはJacksonがあり、Spring Bootでは自動で依存関係に含まれますが、Spring MVCのプロジェクトでも、pleiadesでプロジェクト作成時にチェックを入れることで追加できます。
以下は、DTOクラスを返すことでJSONレスポンスを生成する基本的な例です。
@Controller
public class UserController {
@ResponseBody
@GetMapping("/user")
public UserDto getUserInfo() {
return new UserDto("山田太郎", 28);
}
public static class UserDto {
private String name;
private int age;
public UserDto(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
このコントローラにアクセスすると、ブラウザやPostmanなどで以下のようなJSON形式のレスポンスが確認できます。
{"name":"山田太郎","age":28}
このように、@ResponseBodyはJavaオブジェクトを自動的にJSONに変換し、クライアントにそのままレスポンスとして返します。Spring MVCでは、特別な設定をしなくてもこのような仕組みが動作しますが、内部では「HttpMessageConverter」が地味にがんばってくれています。
なお、Gradle環境でpleiadesを使って開発している場合、Jacksonなど必要な依存関係はプロジェクト作成時にチェックボックスで追加可能です。pom.xmlを使うMavenとは違い、build.gradleで自動的に依存が管理されるので、初心者にも扱いやすくなっています。
JSONレスポンスを返す際に、文字化けが起きる場合は、コントローラの戻り値の文字コードやレスポンスのヘッダー設定などに注意が必要です。また、Javaのgetterメソッドが定義されていないと、プロパティがJSONに含まれないという落とし穴もあるので気をつけましょう。
3. 独自のオブジェクトをJSONとして返す方法(DTOの作成と返却)
Spring MVCでJSONレスポンスをカスタマイズしたい場合、独自のオブジェクトをDTO(データ転送オブジェクト)として作成し、それをコントローラの戻り値として返す方法がよく使われます。
DTOとは、必要なデータだけをまとめたシンプルなJavaクラスのことで、データベースのエンティティとは分けて設計するのが一般的です。こうすることで、セキュリティやメンテナンス性が向上し、API設計の柔軟性も高まります。
以下は、書籍情報を返すサンプルです。
@Controller
public class BookController {
@ResponseBody
@GetMapping("/book")
public BookDto getBookInfo() {
return new BookDto("Spring入門", "佐藤一郎", 2024);
}
public static class BookDto {
private String title;
private String author;
private int year;
public BookDto(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getYear() {
return year;
}
}
}
このコードにアクセスすると、以下のようなJSONレスポンスがブラウザまたはツールで確認できます。
{"title":"Spring入門","author":"佐藤一郎","year":2024}
このように、Javaで定義したBookDtoクラスのプロパティは、自動的にJSON形式に変換されます。これはHttpMessageConverterとJacksonが連携してくれるためで、初心者でも特別な設定をせずに使えます。
重要なのは、各プロパティに対してgetterメソッドを定義することです。これがないと、JacksonがJSON変換時にプロパティを検出できず、レスポンスが空になることがあります。
このようにDTOを使えば、JSONレスポンスの構造を柔軟に設計することができ、メンテナンスや拡張にも強いAPIを構築できます。
4. JSONに含めるプロパティを制御する方法(@JsonIgnoreなどの使い方)
Spring MVCでJSONレスポンスを返す際、場合によっては一部のプロパティをレスポンスに含めたくないことがあります。例えば、パスワードや内部IDなどの機密情報や、クライアント側に不要な情報などです。
このようなときに使えるのが、Jacksonが提供する@JsonIgnoreアノテーションです。このアノテーションを付けたフィールドは、JSONレスポンスに含まれなくなります。
以下はその具体例です。
import com.fasterxml.jackson.annotation.JsonIgnore;
@Controller
public class MemberController {
@ResponseBody
@GetMapping("/member")
public MemberDto getMember() {
return new MemberDto("田中花子", "secret123", "tanaka@example.com");
}
public static class MemberDto {
private String name;
@JsonIgnore
private String password;
private String email;
public MemberDto(String name, String password, String email) {
this.name = name;
this.password = password;
this.email = email;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
}
}
このエンドポイントにアクセスすると、レスポンスにはパスワード情報が含まれず、以下のようなJSONが返ります。
{"name":"田中花子","email":"tanaka@example.com"}
このように、@JsonIgnoreを使うことで、JSONレスポンスの内容を細かく制御できます。特にセキュリティ上重要な情報を誤ってクライアントに返さないようにするためには、非常に有効な手段です。
また、応用として、条件によって表示・非表示を切り替えたい場合は、@JsonViewや@JsonIncludeといった他のアノテーションも活用できますが、まずは@JsonIgnoreを正しく使いこなせるようになることが大切です。
なお、@JsonIgnoreはクラスのフィールドに付けても、getterに付けても動作しますが、どちらかに統一して使うのがトラブル回避のコツです。Spring MVCではJacksonが自動的にそれらを検出してくれるので、使いやすさと信頼性のバランスが良い設計になっています。
このように、SpringでのJSONレスポンスのカスタマイズは、DTOとJacksonのアノテーションを組み合わせることで、安全かつ柔軟に実現することができます。
5. HTTPステータスコードのカスタマイズ方法(ResponseEntityの使い方)
通常、Spring MVCでは@ResponseBodyでJSONレスポンスを返す際、HTTPステータスコードは200(OK)になります。しかし、エラーやリソース未存在など、状況に応じて適切なステータスコードを返したい場面があります。
そこで便利なのがResponseEntityクラスです。これはレスポンスのボディだけでなく、HTTPステータスやヘッダーも一緒に返せるクラスです。Spring MVCでも@Controllerと@ResponseBodyの組み合わせで利用できます。
以下は、条件によってステータスコードを変更する例です。
@Controller
public class ProductController {
@ResponseBody
@GetMapping("/product")
public ResponseEntity<ProductDto> getProduct(@RequestParam int id) {
if (id == 0) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
ProductDto product = new ProductDto("ノートパソコン", 120000);
return new ResponseEntity<>(product, HttpStatus.OK);
}
public static class ProductDto {
private String name;
private int price;
public ProductDto(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
}
この例では、IDが0の場合は404 Not Foundを返し、正しいIDなら200 OKとともにJSONレスポンスを返しています。これにより、APIの信頼性が向上し、クライアント側での処理も明確になります。
ResponseEntityを使えば、今後APIが複雑化しても柔軟に対応できる設計となり、エラー処理や認証失敗時などにも非常に役立ちます。
6. よくあるエラーと対処法(JSONが返らない、構造が崩れる等)
Spring MVCでJSONレスポンスを扱っていると、初心者がよく直面するエラーや落とし穴がいくつかあります。ここでは代表的なパターンとその対処法を紹介します。
① getterメソッドがないためJSONが空になる
JacksonはJavaのgetterメソッドを使ってプロパティを検出します。そのため、getterが定義されていないと以下のようにJSONが空になることがあります。
public class ItemDto {
private String name = "テスト商品";
// getterがないためJSONに出力されない
}
対処法:すべてのフィールドに対してgetXxx()形式のメソッドを定義しましょう。
② DTOのフィールドがnullでJSONに出力されない
Jacksonのデフォルト設定では、値がnullのフィールドも出力されますが、設定によっては省略される場合があります。特に@JsonInclude(Include.NON_NULL)などを付けているときは注意が必要です。
③ @ResponseBodyがついていない
コントローラメソッドに@ResponseBodyをつけ忘れると、戻り値がビュー名として解釈され、JSONが表示されずにエラーになります。
@Controller
public class ErrorExampleController {
@GetMapping("/wrong")
public String wrongResponse() {
return "Hello"; // ビュー名と解釈されてしまう
}
}
対処法:@ResponseBodyをしっかりメソッドにつけましょう。
④ DTOクラスがstaticでない
コントローラ内部に定義したDTOクラスがstaticでないと、Springがインスタンスを生成できず例外が発生することがあります。
対処法:コントローラ内のクラスにはstaticを付けるようにしましょう。
⑤ 依存ライブラリが不足している
JacksonのライブラリがGradleに追加されていないと、JSON変換自体が行われずエラーになります。pleiadesでプロジェクト作成時に「Spring Web」などを選択すれば自動的に入りますが、確認が必要です。
7. JSONレスポンスのカスタマイズが有効なユースケース紹介
JSONレスポンスをカスタマイズする機能は、さまざまなシーンで役立ちます。以下に代表的なユースケースを紹介します。
① フロントエンドとの連携(Ajax・SPA)
ReactやVue.jsなどのフロントエンドライブラリと連携する際、APIからJSON形式でデータを返すことは必須です。@ResponseBodyやResponseEntityを使って、必要な形式でレスポンスを整えることで、画面の動的更新がスムーズに行えます。
② モバイルアプリのバックエンドAPI
iOSやAndroidアプリのバックエンドとしてSpringを利用する場合、JSONレスポンスのカスタマイズは非常に重要です。パフォーマンスや通信量を最適化するためにも、DTO設計や@JsonIgnoreなどの活用が効果を発揮します。
③ 外部サービスとのAPI連携
他のシステムとREST APIでデータ連携する場合、フォーマットが厳格に定められていることがあります。ResponseEntityでステータスを正確に返しつつ、必要なプロパティだけを含めるようなカスタマイズが求められます。
④ エラー時のメッセージ制御
例えば、バリデーションエラーや認証エラーが発生した場合に、適切なステータスコード(400、401など)と一緒にエラーメッセージをJSONで返すと、クライアント側での処理がしやすくなります。
⑤ サーバー内部処理の非公開
Entityクラスそのままを返すのではなく、DTOを使って外部公開する情報を制御することで、内部の構造や不要な情報を漏らさずに済みます。これはセキュリティの観点でも非常に重要です。
このように、JSONレスポンスのカスタマイズはただの「見た目」だけでなく、保守性や安全性、使いやすさに直結する重要な技術です。Spring MVCでしっかり学んでおくことで、将来的に他のAPI開発でも応用が利くスキルになります。
まとめ
本記事では、Spring MVCにおける
次に、JSONレスポンスがどのような仕組みで生成されているのかを確認しました。Spring MVC内部ではHttpMessageConverterが動作しており、JavaオブジェクトをJSONへ変換する処理を担っています。多くの環境ではJacksonが自動的に利用され、開発者は特別な設定を意識しなくてもJSONレスポンスを扱える点が大きな特徴です。この仕組みを知っておくことで、トラブルが発生した際にも原因を切り分けやすくなります。
さらに、DTOを使ったJSONレスポンスの設計についても学びました。DTOを利用することで、必要なデータだけを安全に外部へ公開でき、保守性や可読性の高いAPIを構築できます。getterメソッドの重要性や、staticクラスとして定義する必要性など、初心者がつまずきやすいポイントも押さえました。
また、JsonIgnoreを使ったプロパティ制御や、ResponseEntityによるHTTPステータスコードの制御についても解説しました。これらは実務で非常によく使われる要素であり、単にJSONを返すだけでなく、意味のあるレスポンスを返すために欠かせない考え方です。ステータスコードを正しく返すことで、クライアント側の処理が明確になり、API全体の品質が向上します。
後半では、JSONが返らない場合や構造が崩れる場合など、よくあるエラーとその対処法を整理しました。getterの不足、アノテーションの付け忘れ、依存関係の不足など、どれも実際の開発現場で頻繁に遭遇する内容です。事前に知っておくことで、無駄な調査時間を減らし、効率的に開発を進めることができます。
最後に、JSONレスポンスのカスタマイズが活用される具体的なユースケースを紹介しました。フロントエンドとの連携、モバイルアプリのバックエンド、外部サービスとのAPI連携など、Spring MVCとJSONは幅広い場面で使われています。本記事の内容を理解しておけば、これらの場面でも自信を持って対応できるはずです。
まとめのサンプルプログラム
@Controller
public class SummaryController {
@ResponseBody
@GetMapping("/summary")
public ResponseEntity<SummaryDto> getSummary() {
SummaryDto dto = new SummaryDto("JSON理解", "ResponseBodyとDTOの基本を習得");
return new ResponseEntity<>(dto, HttpStatus.OK);
}
public static class SummaryDto {
private String title;
private String message;
public SummaryDto(String title, String message) {
this.title = title;
this.message = message;
}
public String getTitle() {
return title;
}
public String getMessage() {
return message;
}
}
}
生徒「
先生「内部ではHttpMessageConverterとJacksonが動いているんだよ。仕組みを知ると安心できるよね。」
生徒「DTOを使う理由も分かってきました。必要な情報だけ返せるのは大事ですね。」
先生「その通り。セキュリティや保守性の面でもDTOは欠かせない考え方だよ。」
生徒「ResponseEntityでステータスコードを返せるのも便利だと思いました。」
先生「API開発では、データだけでなく意味のあるレスポンスを返すことが重要だからね。」
生徒「エラーの原因も整理できたので、今後は落ち着いて対応できそうです。」
先生「今回の内容を押さえておけば、Spring MVCでのJSONレスポンスは十分実践レベルだよ。」