実践
JSON Server使いこなし
第1回 モックサーバーの起動とリソース処理

APIモックサーバーを起ち上げる必要があるときに利用できる、JSON Serverを解説します。まずはモックサーバーの起動とリソース処理について見てみましょう。

2017年09月21日発行

目次

はじめに

新規でフロントエンドの開発を行う際、機能の実装に必要なAPIが完成していないことや、なんらかの制約があってローカル環境からはAPIが使えない、といった状況に遭遇することがあります。そのような状況で作業を進める場合、APIモックサーバーが必要になるかと思います。こういったときに役立つのが、今回紹介するNode.jsベースのライブラリ、JSON Serverです。

JSON Serverの公式ページを見ると、冒頭に次のような記述があります。

Get a full fake REST API with zero coding in less than 30 seconds (seriously)

「コーディング不要で、30秒以内にRESTfulなAPIモックサーバーを立てるよ(マジで)」とでも訳せるのでしょうか。

JSON Serverはこの言葉のとおり、かなり手軽にRESTfulなモックサーバーを起ち上げることができます。

サンプルリポジトリ

本記事で紹介するデモは、次のリポジトリからダウンロード、またはクローンできます。併せて参照してください。

codegrid/2017-json-server

モックサーバーを起ち上げる

JSON Serverは、モジュールとしてコードに組み込んで利用することもできますが、コマンドラインツールとして利用することで、より簡単にモックサーバーを起ち上げることができます。手順は次の3ステップのみです。

STEP1:インストール

まず、JSON Serverをグローバルもしくはローカルにインストールします。

# グローバルにインストールする場合
npm install -g json-server

# ローカルにインストールする場合
npm install --save-dev json-server

STEP2:モックデータの作成

モックデータを任意のファイル名で、JSON形式で作成します。本記事ではdb.jsonという名前で作成することにします。

db.json
{
  "articles": [
    { "id": 1, "title": "json-server", "author": "typicode"},
    { "id": 2, "title": "faker.js", "author": "Marak"}
  ],
  "profile": { "name": "typicode" }
}

ここで指定するJSONは、ルート直下のメンバーとして構成されるキー文字列がREST APIのリソース名にあたり、それらキーに割り当てられた値がリソースの内容に相当することになります。

JSON定義時の注意点

リソースの内容には、必ず配列かオブジェクトを定義する必要があります。たとえば次のように、単なる文字列を指定した場合は、モックサーバー起動時にエラーとなるので注意してください。

{"profile": "typicode"}

また、リソースパスを階層的なURIにするために、次のようにキー文字列にスラッシュ(/)を含ませて定義した場合もエラーになります(これについての対策は次回紹介します)。

{"profile/author": "typicode"}

STEP3:モックサーバーの起動

作成したJSONのファイル名を引数にjson-serverを実行し、モックサーバーを起動します。

# グローバルにインストールした場合
json-server --watch db.json

# ローカルにインストールした場合
$(npm bin)/json-server --watch db.json

オプションの指定

--watchオプションを付けることでモックデータであるdb.jsonが監視され、手動による修正を行った場合でも、変更内容がAPIレスポンスに反映されるようになります。オプションの指定は、次のようにjson-server.jsonにまとめておくことで省略することもできます。

{
  "watch": true
}

他にも、ホスト名、ポート番号の変更をはじめ、各種設定の変更が可能になっています。詳しくは公式ページをご覧ください。

以上の3ステップで、モックサーバーとして利用可能な状態になります。

次節以降、モックサーバーの利用方法について紹介していきます。また、次の手順でサンプルリポジトリのデモを動かすことで、動作確認しつつ読み進められるようにしてありますので、よろしければ試してみてください。

git clone https://github.com:codegrid/2017-json-server.git
cd 2017-json-server
npm i
npm run demo01a

モックサーバー起動時の状態

モックサーバーを起動すると、次のようにアクセス可能なリソースのURIがターミナルに表示されます。

モックサーバー起動時のターミナルの表示

モックデータとして記述した、articlesやprofileといったキー文字列をリソース名としたURIが、表示されているのがわかります。

また、表示されているように「s」+「エンター」キーでデータのスナップショット(データの保存)が撮れます。スナップショットを撮ると、次のようにdb-連番.jsonという形式のファイル名でデータが保存されます。

データのスナップショットファイル

JSON Serverでは、POST/PUT/DELETEなどのリソースを更新するメソッドが実行されると、モックデータの物理的な書き換えが行われるので、その時々のデータ状態の保存に使用してもよいでしょう。

Homeページであることを示す http://localhost:3000/ をブラウザで表示すると、ほぼ同じ内容の次のようなページが表示されます。

ブラウザでの表示

リソースを取得する

モックアップサーバーを起動したら、まずリソースの取得方法を見てみます。

Homeページにある /articles をクリックすると、モックデータに定義されたarticlesリソースのみが返され、次のように表示されます。

[
  { "id": 1, "title": "json-server", "author": "typicode"},
  { "id": 2, "title": "faker.js", "author": "Marak"}
]

また、http://localhost:3000/articles/1 のようにエンドポイントURIの末尾にIDを指定することで、指定IDに一致する特定のリソースデータのみを表示させることもできます。

{ "id": 1, "title": "json-server", "author": "typicode"}

これらの処理は、いわゆるGETメソッドによるリソースの取得処理に相当します。当然、プログラムを使用して、これらの取得処理を記述することもできます。たとえば、Fetch APIを利用したコードで書いた場合、次のような記述になります。

fetch('/articles/1', {method: 'GET'})
    .then(res => res.json()).then(console.log)

http://localhost:3000/ を表示した状態で、DevToolsのConsoleタブを開き、上記コードをペーストし実行すると、次のようにリソースデータを取得できることが確認できます。

Consoleタブでのリソースデータの取得確認

静的ページの設置方法

JSON Serverでは、プロジェクトディレクトリ直下のpublicディレクトリ内に配置されたHTMLファイルを、ファイルサーバーとしてhttpで公開する機能を持っています。

たとえばプロジェクトディレクトリにて次のコマンドを入力し、localhost:3000にアクセスした場合、hello worldと表示されるようになります。

mkdir public
echo 'hello world' > public/index.html

また、public以外のディレクトリに配置したい場合は、--staticオプションで任意のディレクトリを指定します。

# ./wwwディレクトリを指定
json-server db.json --static ./www

DevToolsではなく、実際のHTML内からのリソースの取得処理を確認したい場合は、この機能を利用するとよいでしょう。

リソースの追加/更新/削除

JSON Serverでは、lowdbというlodash APIベースのデータベースライブラリを使用することで、リソースの更新処理にも対応できるようになってます。

具体的には、POST/PUT/DELETEメソッドを使用した場合、リソースに対する追加/更新/削除が行われます。これらの処理ではモックデータの本体であるJSONファイルも物理的に書き変えられてしまうので、必要に応じバックアップをとっておく、もしくはJSファイルを経由してJSONファイルの変更を抑止してもよいでしょう(この節末のコラム枠で解説します)。

リソースの追加

DevToolsのConsoleタブにて次のコードを実行すると、bodyプロパティで指定したJSONデータが、指定したリソースに追加登録されます。

fetch('/articles', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        'title': 'react',
        'author': 'facebook'        
    })
}).then(res => res.json()).then(console.log);

リソースを追加する場合はIDを含めず、対象とするリソースのエンドポイントURIのみを指定し、POSTメソッドを実行します。POSTメソッドによるAPIリクエストが発行されると、送信されたJSONにIDが付与され、新規リソースデータとして追加登録されたのち、レスポンスデータとして返却されます。

追加登録されたリソースデータがレスポンスデータとして返却されている

追加対象となったリソースである /articles を表示してみると、次のようにPOSTされたJSONデータが、リソースデータの末尾に追加されていることが確認できます。

[
  { "id": 1, "title": "json-server", "author": "typicode"},
  { "id": 2, "title": "faker.js", "author": "Marak"},

  // 追加されたデータ
  { "id": 3, "title": "react", "author": "facebook"}
]

リソースの更新

リソースを更新する場合は、エンドポイントURIの末尾に更新対象とするIDを指定し、PUTメソッドを実行します。次の例では、先程追加したリソースデータを上書きするように、IDに3を指定しています。

fetch('/articles/3', { // IDに3を指定
    method: 'PUT',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        'title': 'angular',
        'author': 'google'        
    })
}).then(res => res.json()).then(console.log);

指定IDに一致するリソースデータが更新されたのち、対象となったJSONがレスポンスデータとして返されます。

更新されたリソースデータがレスポンスデータとして返却されている

/articles を確認してみると、対象データが更新されていることがわかります。

[
  { "id": 1, "title": "json-server", "author": "typicode"},
  { "id": 2, "title": "faker.js", "author": "Marak"},

  // 更新されたデータ
  { "id": 3, "title": "angular", "author": "google"}
]

リソースの削除

リソースを削除する場合も更新処理と同様に、削除対象とするリソースIDを含めたURIを指定し、DELETEメソッドを実行します。データ送信は不要なため、POSTやPUTの場合と異なりheadersbodyプロパティの記述は不要です。

先程と同様に、IDが3のリソースデータを削除するには、次のように記述します。

fetch('/articles/3', {method: 'DELETE'}).then(console.log);

DELETEの場合は対象リソースを削除したのち、次のようなResponseオブジェクトが返されます。

リソースを削除をしたのでResponseオブジェクトが返された

/articles を確認すると、対象データが削除されていることがわかります。

[
  { "id": 1, "title": "json-server", "author": "typicode"},
  { "id": 2, "title": "faker.js", "author": "Marak"}
]

JSONファイルの変更を抑止する方法

JSONファイルの代わりにJSファイルを使用することで、モックデータを動的に生成させることができます。次の例では1000件のユーザデータを動的に生成しています。

// index.js
module.exports = () => {
  const data = { users: [] }
  // Create 1000 users
  for (let i = 0; i < 1000; i++) {
    data.users.push({ id: i, name: `user${i}` })
  }
  return data
}

JSON Serverの起動時は、JSファイルを指定します。

json-server index.js

この場合、物理的なデータファイルが存在しないため、物理ファイルの更新は行われず、メモリ上のデータのみが更新されます(物理ファイルが存在しない状態でも、「s」+「エンターキー」によるスナップショットの書き出しは可能)。

db.jsonのように利用したいデータファイルがすでにあり、ファイルの書き換えを抑止したい場合は、JSファイルにて読み込んだモックデータを返すようにするとよいでしょう。

// index.js
module.exports = () => require('./db.json');

ここまでのまとめ

モックデータとなるJSONファイルを1つ用意するだけで、手軽にモックサーバーを起ち上げることができるJSON Serverの導入編を紹介しました。

その手軽さもさることながら、ロジックの記述を必要としないデータの更新処理が可能である点についても、業務系システムのように多く更新系APIを扱う必要のある開発においては、大きな利点であると言えるのではないでしょうか。

次回は「フィルタリングやソート処理を行うためのクエリ機能」「リソースパスを任意のパターンに置き換えるルーティング設定」について紹介します。

森 大典
森 大典
フロントエンド・エンジニア

大手電機メーカーを中心とした基幹系システム開発プロジェクトにSE兼プログラマとして多数参画。WEBシステム、C/S、POSレジ、無線ハンディ、汎用機(COBOL)、工場設備(シーケンス制御)、など、多数のシステム構築の実務経験を積む。2015年株式会社ピクセルグリッドへ入社。ブログにて発信しているチュートリアル、リファレンス関連の記事は幅広い層に利用されている。