Express v4.xでJSONのリクエスト/レスポンスを取得する正しい方法


ExpressでJSONのリクエストを受け付けて、JSONのレスポンスを返す処理のメモです。

たまにExpressで検証などすることがあるのですが、いつもJSONの扱い方を検索している気がするので自分でもまとめておくことにしました。

また、検索するとbody-parserをインストールするように書かれている記事が多いのですが、2020年5月現在はExpress本体にミドルウェアが用意されています。
よって、以下の方法がおそらく現在最もシンプルで標準的な手順になると思います。(公式マニュアル読めばいいという話でもありますが)

Expressについて

自分はこれまでなんとなくExpressを使っていたので改めてまとめてみました(ご存知の方は飛ばして下さい)。

Expressは、node.jsのWebフレームワークですが、Webフレームワークと言ってもPHPのDjangoやRubyのRailsのようなフルスタックのフレームワークではなく、PythonのFlaskやRubyのSinatra、PHPであればLaravelではなくSilexなどにあたり、他の言語だと軽量フレームワーク相当のものです。

具体的に以下の機能を提供しています。

  • HTTPリクエスト/レスポンスの処理
  • ルーティング
  • ミドルウェア: LaravelのミドルウェアやRailsのフィルタにあたります
  • 静的ファイルの配信
  • プロジェクト生成コマンド

テンプレートはデフォルトでは入っていないので、必要に応じて追加します。
(参照: Express でのテンプレート・エンジンの使用)

事前準備

ここから本題、まず確認用のプロジェクトを作成します。

$ mkdir express-json-sample && cd express-json-sample
$ npm init -y
$ npm install express --save

リクエストボディのJSONを受け取る

ところで、Expressのリクエストボディをreq.bodyで取得しようとしてもundefinedで、はじめて使うと「?」となります。

これについては「API リファレンス req.body」に
「By default, it is undefined, and is populated when you use body-parsing middleware such as express.json() or express.urlencoded().」と記載されているとおりデフォルトの動作で、適当なbody-parserの使用を宣言する必要があります。

記事冒頭で書いたとおり、4.x系ではbody-parserのインストールは不要で、JSONをパースするミドルウェアexpress.json()が用意されています。

以下のように、express.json()app.useに指定します。

const express = require('express')
const app = express()
app.use(express.json())

app.post('/', function (req, res) {
  console.log(req.body);
  res.send('Got a POST request')
})

app.listen(3000, () => console.log('Example app listening on port 3000!'))

curlで動作確認

$ curl http://localhost:3000 -X POST -H "Contion/json" -d '{"name":"鈴木一郎", "age":55}' 

ターミナル側の出力は以下の通り、ちゃんとパースされたオブジェクトを確認できます。

$ node app.js 
Example app listening on port 3000!
{ name: '鈴木一郎', age: 55 }

レスポンス

レスポンスのボディにJSONを返す場合は、res.json([body])メソッドを使用します。
res.jsonメソッドは、ヘッダーにContent-Typeapplication/jsonを追加、オブジェクトをJSON.stringify()して返してくれます。

上記のコードを以下のように書き換えます。

app.post('/', function (req, res) {
  console.log(req.body);
  res.json({'msg':'Got a POST request'});
})

curlで実行確認、レスポンスヘッダーも出力してみます。

$ curl http://localhost:3000 -X POST -H "Contention/json" -d '{"name":"鈴木一郎", "age":55}' -D -
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 28
ETag: W/"1c-/EdmnxF6KOt7WkTBgbBDKhXsS7U"
Date: Sat, 30 May 2020 00:04:11 GMT
Connection: keep-alive

{"msg":"Got a POST request"}

その他参考情報

記事を書いている際に調べたことをついでにメモしておきます。

通常のフォームリクエストのボディ

Content-Typeapplication/x-www-form-urlencodedのケースです。
express.urlencodedミドルウェアをセットすればOKです。

const express = require('express')
const app = express()
app.use(express.urlencoded({ extended: true }))
app.post('/', function (req, res) {
  console.log(req.body);
  res.send('Got a POST request')
})

動作確認

$ curl -X POST http://localhost:3000 -d 'name=鈴木一郎&age=55'

ターミナル側の出力、パラメータをオブジェクトに変換して取得できます。

$ node app.js 
Example app listening on port 3000!
{ name: '鈴木一郎', age: '55' }

調査中に試した他のレスポンス ボディの返し方メモ

Proper way to return JSON using node or Express

var http = require('http');

var app = http.createServer(function(req,res){
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ a: 1 }, null, 3));
});
app.listen(3000);