Springの@ResponseBodyとは?サーバーからJSON形式で値を返す方法をやさしく解説!
新人
「先輩、Springでサーバーから値を返すときって、どうやってJSON形式にするんですか?」
先輩
「それなら、@ResponseBodyというアノテーションを使えば、JavaのオブジェクトをJSONに変換してレスポンスとして返せるよ。」
新人
「JSONって聞いたことありますけど、実はよくわかってなくて……」
先輩
「じゃあ、まずは@ResponseBodyとは何かと、JSONの基本について順番に見ていこうか!」
1. @ResponseBodyとは?
Springフレームワークでは、サーバー側で処理した結果をクライアントに返すために、さまざまな方法が用意されています。その中でも@ResponseBodyアノテーションは、Javaの値やオブジェクトをHTTPレスポンスの本文(Body)としてそのまま返すために使います。
通常、Spring MVCでは@Controllerクラスのメソッドが文字列を返すと、それをビュー名として解釈してHTMLなどのテンプレートを探しに行きます。しかし、@ResponseBodyをメソッドに付けると、その戻り値はビューではなく、HTTPレスポンスのデータとしてそのままクライアントに返されます。
具体的には、次のようなコードでJavaの文字列やオブジェクトを直接レスポンスとして返すことができます。
@Controller
public class HelloController {
@ResponseBody
@GetMapping("/hello")
public String sayHello() {
return "こんにちは、Springの世界へようこそ!";
}
}
上記のコードでは、/helloというURLにアクセスすると、「こんにちは、Springの世界へようこそ!」という文字列がそのままブラウザに表示されます。テンプレート(HTML)を使わず、純粋なレスポンスとして文字列を返しているのが特徴です。
では、次に「JavaのオブジェクトをJSON形式に変換して返す」方法を見てみましょう。これは@ResponseBodyを使うことで、Springが自動的にやってくれます。
@Controller
public class UserController {
@ResponseBody
@GetMapping("/user")
public User getUser() {
return new User("taro", 25);
}
}
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
このようにUserというJavaのクラスを作成し、そのインスタンスをメソッドで返すと、Springが自動的にJSONに変換してレスポンスとして返してくれます。つまり、@ResponseBodyは「Javaの値をJSONに変換してサーバーから返す」ための便利な仕組みなのです。
2. JSONとは?
JSON(ジェイソン)は、「JavaScript Object Notation」の略で、データを軽量にやりとりするためのフォーマットです。人間にも読みやすく、機械にも扱いやすいのが特徴で、今ではWeb開発の標準的なデータ形式になっています。
例えば、次のような形式がJSONです。
{
"name": "taro",
"age": 25
}
上記のように、キーと値をセットにしたデータを中かっこ{}で囲んで表現します。キーは文字列で、値は文字列・数値・配列・オブジェクトなどさまざまなタイプが使えます。
JSONは、サーバーとクライアントの間でデータを交換する際によく使われます。たとえば、SpringのアプリケーションでJavaオブジェクトをJSONに変換し、ブラウザやJavaScript側に渡すことで、画面上にデータを動的に表示することができます。
Springの@ResponseBodyを使えば、Javaのオブジェクトを特別な設定なしで簡単にJSONとして返すことができるため、とても便利です。SpringにはJacksonというライブラリが標準で組み込まれており、自動でJSON変換してくれます。
なお、JSONの形式に対応していないデータを返そうとするとエラーになることもあります。たとえば、privateなフィールドにgetterメソッドがない場合は、JSONに変換できずにレスポンスエラーになることがあります。JSONで値を返すには、適切な構造のJavaクラスを作ることが大切です。
3. HTMLやJavaScriptからのリクエストに対して、@ResponseBodyでJSONを返す方法
Springの@ResponseBodyは、サーバー側のJavaコードだけでなく、フロントエンドのHTMLやJavaScriptと連携して使うこともできます。例えば、ブラウザ側からボタンを押してリクエストを送り、サーバーからJSON形式のレスポンスを受け取るような場面でよく使われます。
実際に、JavaScriptでfetch関数を使ってSpringアプリケーションのエンドポイントにアクセスすることで、JSON形式のレスポンスを取得できます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ユーザー情報の取得</title>
</head>
<body>
<h1>ユーザー情報を取得する</h1>
<button onclick="loadUser()">読み込む</button>
<div id="result"></div>
<script>
function loadUser() {
fetch('/user')
.then(response => response.json())
.then(data => {
document.getElementById('result').innerText =
'名前: ' + data.name + ', 年齢: ' + data.age;
})
.catch(error => {
console.error('エラーが発生しました', error);
});
}
</script>
</body>
</html>
上記のHTMLファイルは、ブラウザで表示して「読み込む」ボタンをクリックすると、JavaScriptが/userというURLにリクエストを送信します。サーバー側で@ResponseBodyを使ってJSONレスポンスを返すことで、JavaScriptでそのデータを受け取り、画面に表示できます。
このように、Springの@ResponseBodyは、サーバーからフロントエンドへのJSON形式でのデータ送信にとても便利です。
4. JavaのオブジェクトをJSON形式で返す実装例
次に、Springアプリケーションで実際にJavaのオブジェクトをJSONとして返す具体的な実装例を見てみましょう。この例では、複数のフィールドを持つオブジェクトを定義して、それをレスポンスとして返します。
@Controller
public class ProductController {
@ResponseBody
@GetMapping("/product")
public Product getProduct() {
return new Product(1001, "ノートパソコン", 120000);
}
}
class Product {
private int id;
private String name;
private int price;
public Product(int id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}
public int getId() { return id; }
public String getName() { return name; }
public int getPrice() { return price; }
}
このコードでは、ProductというJavaのクラスを用意し、id、name、priceという3つのプロパティを持たせています。そして、コントローラのメソッドgetProductからそのオブジェクトを返しています。
クライアントが/productにアクセスすると、以下のようなJSONレスポンスが返されます。
{
"id": 1001,
"name": "ノートパソコン",
"price": 120000
}
このように、Springはオブジェクトの中身をJSON形式に変換して、サーバーからそのままクライアントに返してくれるのです。非常にシンプルかつ強力な機能であり、Webアプリケーション開発において欠かせない存在となっています。
5. データクラス(DTO)を使って値を返す方法
より現実的なアプリケーションを開発するときは、データを整理して管理するためにDTO(Data Transfer Object)と呼ばれるクラスを使うのが一般的です。DTOは、サーバーとクライアントの間でやりとりするデータを入れるための専用クラスです。
Springでは、このDTOクラスをコントローラの戻り値として使うことで、レスポンスとしてのJSONデータを整理して返すことができます。
@Controller
public class OrderController {
@ResponseBody
@GetMapping("/order")
public OrderDto getOrder() {
return new OrderDto(5001, "カメラ", 2, 80000);
}
}
class OrderDto {
private int orderId;
private String productName;
private int quantity;
private int total;
public OrderDto(int orderId, String productName, int quantity, int total) {
this.orderId = orderId;
this.productName = productName;
this.quantity = quantity;
this.total = total;
}
public int getOrderId() { return orderId; }
public String getProductName() { return productName; }
public int getQuantity() { return quantity; }
public int getTotal() { return total; }
}
この例では、OrderDtoというDTOクラスを定義しており、注文ID・商品名・数量・合計金額といった情報をフィールドに持っています。これをコントローラで生成して返すことで、JSON形式のレスポンスが生成されます。
{
"orderId": 5001,
"productName": "カメラ",
"quantity": 2,
"total": 80000
}
DTOを使うメリットは、必要な項目だけをクライアントに渡せる点や、APIの設計が明確になる点です。特に業務用システムでは、ドメインモデルとDTOを分けて管理することで、責務が整理されて保守しやすい設計になります。
Springでは、DTOと@ResponseBodyを組み合わせることで、サーバーからのJSONレスポンスを柔軟に制御できるようになります。今後、より大きなアプリケーションを作る際には、DTOを活用することが基本となります。
6. よくあるエラーと原因(406エラー、500エラーなど)
Springで@ResponseBodyを使ってJSONレスポンスを返すとき、初心者の方がよく遭遇するエラーとして「HTTPステータスコード406」や「500エラー」があります。ここではそれぞれの原因と対処方法をやさしく解説します。
まず、「406 Not Acceptable」エラーは、クライアントが要求したレスポンスの形式(たとえばapplication/json)をサーバー側が生成できないときに発生します。主な原因としては、戻り値のクラスにgetterメソッドがない場合や、Springの設定が正しくないケースです。
Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
次に、「500 Internal Server Error」は、サーバー内部で予期しない例外が発生したときに表示されます。Javaオブジェクトの初期化ミスや、nullのまま返そうとした場合によく起こります。
java.lang.NullPointerException
これらのエラーを防ぐには、クラスの定義が適切か、getterがすべて揃っているか、返す値がnullになっていないかを確認することが大切です。また、サーバーログに出力されるメッセージをよく読み、どの部分で例外が発生しているかを特定する習慣を身につけましょう。
7. 初心者がつまずきやすいポイント(ゲッターがない、DTOの定義ミスなど)
Springで@ResponseBodyを使う際に、初心者の方が特につまずきやすいポイントは、Javaクラスの定義ミスです。特に以下のようなケースはJSONレスポンスが正しく返らない原因になります。
① getterメソッドが定義されていない
Springでは、戻り値のJavaオブジェクトをJSONに変換する際、フィールドに対応するgetterメソッドを使います。そのため、getterがないとデータがJSONに含まれません。
class User {
private String name;
private int age;
// getterがない
}
上記のような定義だと、Springはnameやageの値を取り出せないため、JSONとして正しく変換できません。
② DTOクラスにデフォルトコンストラクタがない
Jacksonなどのライブラリでは、デフォルトコンストラクタ(引数なしのコンストラクタ)がないと、うまく変換できないケースがあります。
class Product {
private int id;
private String name;
// 引数ありコンストラクタしかない
public Product(int id, String name) {
this.id = id;
this.name = name;
}
}
このような場合、次のように引数なしのコンストラクタを追加しておくと安全です。
public Product() {
// 空のコンストラクタ
}
③ フィールドがpublicのままになっている
Javaでは、基本的にフィールドはprivateにしてgetterでアクセスするのが一般的です。publicにしても動く場合はありますが、セキュリティや保守性の観点からも避けるべきです。
8. @ResponseBodyを使うときの注意点とポイント
最後に、Springの@ResponseBodyを使う際の注意点と実践的なポイントを整理しておきましょう。JSONレスポンスを扱うためには、ちょっとした工夫やルールを守ることが安定した開発につながります。
① 戻り値の型に気をつける
メソッドの戻り値がプリミティブ型(文字列や数値)であればそのまま返せますが、複雑なオブジェクトの場合は必ずDTOなど明確な構造を持つクラスを使いましょう。戻り値がMapやListのときも、JSONに変換できます。
@ResponseBody
@GetMapping("/list")
public List<String> getList() {
return List.of("りんご", "みかん", "ぶどう");
}
② Content-Typeの指定
クライアントと通信する際に、Content-Typeがapplication/jsonになっていないと、思った通りに動作しないことがあります。produces属性を明示的に指定しておくのもおすすめです。
@GetMapping(value = "/info", produces = "application/json")
@ResponseBody
public InfoDto getInfo() {
return new InfoDto("Spring Boot", "2.7");
}
③ デバッグはブラウザだけでなくPostmanなども活用
ブラウザで直接URLにアクセスしてレスポンスを確認する方法もありますが、Postmanなどのツールを使えば、ヘッダーの確認やパラメータ付きのテストも簡単にできます。開発初期から積極的に活用することで、エラーの早期発見につながります。
④ 自動でJSONに変換する仕組みを理解しておく
Springでは、内部的にJacksonというライブラリが動いていて、JavaのオブジェクトをJSONに変換しています。この仕組みによって、@ResponseBodyをつけるだけで自動的にJSONが生成されるのです。
ただし、Jacksonの動作をカスタマイズしたい場合や、日付形式を変更したい場合などは、アノテーション(例:@JsonFormat)を使って制御できます。そこまで踏み込む場合は、より詳しいSpringやJacksonの知識が必要になります。