LoginSignup
3
6

More than 5 years have passed since last update.

[*その他*] アプリからの外部データの取得(JSONP編)

Last updated at Posted at 2015-12-08

はじめに

アプリから、外部のサーバーのデータを取りたい場合のJSONP編。

JSONPとは

通常、異なるドメインに対してAjax通信をしようとすると怒られる。
これをクロスドメイン制約という。

XMLHttpRequest cannot load http://exampleexample.com/. 
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://example.com/' is therefore not allowed access.

それでも外部のサーバーのデータを取るのは不可欠なので、

http://example.com/jsonp_project/JsonpServlet?callback=displayCustomer

上記のようなURLでアクセスした時に、
callbackパラメーターの値をサーバー側で受け取り、

displayCustomer([{"age":16,"name":"テスト太郎"}])

のようなJavaScriptの関数を呼び出す形式でサーバー側からJSONデータ返ってくるようにしておく。
displayCustomerがクライアント側で呼び出したいJavaScriptの関数名となっている。
この関数名は任意のものにして、callbackパラメーターとして設定しとけばよい。
受け取ったデータを

<script>
  displayCustomer([{"age":16,"name":"テスト太郎"}])
</script>

な感じで画面側に追加して、クライアント側で定義してあるJavaScriptの関数(この場合displayCustomer)を実行することで、外部のデータを取得した上での処理を実行するというのがJSONP。

scriptタグが外部のソースを読み込みこめることを利用している。

手順

サーバー側でJSON形式にてデータを返すようにする。
今回はサーブレットで適当に作ったデータをJSONで返すように実装。
実際はデータベースからデータを取得して

servlet
@WebServlet(name = "JsonpServlet", urlPatterns = {"/JsonpServlet"})
public class JsonpServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        // URLからcallbackパラメーターに設定されている値を取得
        String callback = request.getParameter("callback");

        Customer[] customers = {
            new Customer("テスト太郎", 16)
        };

        // JSONにエンコード
        String jsonText = JSON.encode(customers);

        String responseData = "";
        if(callback == null || "".equals(callback)){
            responseData = jsonText;
        }else{
            // ここで関数名(JSON)の形式でレスポンスを返すように設定
            responseData = callback + "(" + jsonText + ")";
        }

        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.print(responseData);
    }
}

画面はボタンがあって、それを押したらJSの関数を実行するのみ。

html
<ons-page>
    <ons-toolbar>
        <div class="center">AjaxJSON</div>
    </ons-toolbar>

    <div style="text-align: center">
        <br>
        <ons-button onclick="addScript()">
            JSONP
        </ons-button>

        <div id="ajax"></div>
    </div>
</ons-page>

callbackパラメーターにクライアント側で呼びたいJS関数の名前を指定。

js
// ボタンが押された時にデータを受け取ってscriptタグとして画面に追加
function addScript(){
    var script = document.createElement('script');
    script.src = 'http://example.com/jsonp_project/JsonpServlet?callback=displayCustomer';
    document.body.appendChild(script);
}

// 上記で「関数名(JSON)」の形式でスクリプトが追加され、これが呼ばれる
function displayCustomer(data){
    for(i = 0; i < data.length; i++){
        $("#ajax").append("<div>" + data[i].name + "</div>");
    }
}

実行結果

ボタンを押下するとボタンの下に取得したデータが表示される。
スクリーンショット 2015-12-08 17.08.44.png

まとめ

気象情報APIのようなJSONPを提供しているところがあるので、そういうところのAPIを利用したり、サーバー側でいい感じに返すようにしたらいいと思いました。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6