CompojureとjQueryでWebアプリを作る No.5（JSONデータを返す）

Server側からtextデータしか返却できないとServer側もClient側もいろいろと面倒なので、CompojureでJSONデータを返却できるようにしてみる。

# ring関連のライブラリを使用する（project.cljの変更）

この変更は使うライブラリが増えるので、project.cljファイルも変更対象。
追加するのはring関連のライブラリ。

```clj:project.clj
(defproject greet "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [compojure "1.1.8"]
                 ;↓の２つのS式を追加。カッコのネストに注意。
                 [ring/ring-core "1.2.0"]
                 [ring/ring-json "0.2.0"]]
  :plugins [[lein-ring "0.8.11"]]
  :ring {:handler greet.handler/app}
  :profiles
  {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
                        [ring-mock "0.1.5"]]}}
  :web-content "public")
```

# Server側（handler.clj）の変更

続いてhandler.cljの変更。変更する点は、

- ring関連で使用する関数のrequire宣言を追加
- POSTの返却データをclojureの連想配列データ化
- Webアプリ全体のレスポンスのJSON化（をしている感じ？）

の３本立て。ではコードを記載。尚、見やすさの為に前回のコメントは全て削除してある。

```clj:handler.clj
(ns greet.handler
  (:require [compojure.core :refer :all]
            [compojure.handler :as handler]
            [compojure.route :as route]
            ;次の２つのS式を追加。カッコのネストに注意。
            ;ring関連で使用する関数のrequire宣言を追加している。
            [ring.util.response :refer [resource-response response]]
            [ring.middleware.json :as middleware]))

(defroutes app-routes
  (GET "/" [] "Hello World")
  (POST "/post_name" [first_name last_name]
    ;POSTの返却データをclojureの連想配列データ化。
    ;生成した連想配列データは、response関数で括る事。
    (response {:value (format "Hello, %s %s" first_name last_name)}))
  (route/files "/")
  (route/resources "/")
  (route/not-found "Not Found"))

(def app
  ;Webアプリ全体のレスポンスのJSON化（をしている感じ？）
  (-> (handler/api app-routes)
      (middleware/wrap-json-body)
      (middleware/wrap-json-response)))

```
これでServer側から返却されるデータがJSON化される。


# Client側（greet.html）の変更

実は前回の「[動作確認（異常系）](http://qiita.com/oicawa/items/8a14d3633a7d981ee7a0#1-3)」と似ている。

修正項目は、

- `ajax`メソッドの`dataType`を`"json"`に変更
- responseで受信したデータがJSONデータになっているので、success時のイベントハンドラ内のロジックをJSONから必要なデータを抽出して使うように変更

の２つ。

```html:greet.html
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">google.load("jquery", "1");</script>
    <script type="text/javascript">
      function greet(first_name, last_name) {
        $("#greeting_area").text("** Loading... **");
        $.ajax({
          type: "post",
          // ajaxメソッドのdataTypeを"json"に変更
          dataType: "json",
          data: {
            "first_name": first_name,
            "last_name": last_name
          },
          cache: true,
          url: "http://localhost:3000/post_name",
          success: function (greet_message) {
            // 受け取ったgreet_messageはJSONデータなので、
            // メンバ変数？のvalueに挨拶文が格納されている。
            $("#greeting_area").text(greet_message.value);
          },
          error: function(xhr, status, err) {
            var message = "Error occured: status=" + status + ", err=" + err;
            $('#greeting_area').html(message);
          }
        });
      }
      $(function(){
        $("#greet_button").click(function() {
          var first_name = $("input[name='first_name']").val();
          var last_name = $("input[name='last_name']").val();
          greet(first_name, last_name);
          return false;
        });
      })
    </script>
  </head>
  <body>
    <form action="unused">
      <table>
        <tr>
          <td>First Name:</td>
          <td><input name="first_name" type="text" value="" /></td>
        </tr>
        <tr>
          <td>Last Name:</td>
          <td><input name="last_name" type="text" value="" /></td>
        </tr>
      </table>
      <div><input id="greet_button" type="submit" value="Greet" /></div>
    </form>
    <div id="greeting_area"></div><br/>
  </body>
</html>

```

これでOKなはず。

# 動作確認

例によっていつもの[http://localhost:3000/greet.html](http://localhost:3000/greet.html)にアクセスし、First NameとLast Nameを入力してGreetボタンをクリックする。
次のように表示されればOK。


![JSON受信](https://qiita-image-store.s3.amazonaws.com/0/39876/94c6e882-9df1-53f6-21d4-cb6ab55e6217.png)


大丈夫そうっすね。