2012年8月29日水曜日

Android ASP.NET(MVC2)で作成したWebAPIに接続する その4(JSON)

以前まで作成したWebAPIはXML文字列を返すものでした。
Android ASP.NET(MVC2)で作成したWebAPIに接続する その1
Android ASP.NET(MVC2)で作成したWebAPIに接続する その2
Android ASP.NET(MVC2)で作成したWebAPIに接続する その3

Android側ではXML文字列を解析するのですが、スマートフォンでXMLの解析は負荷が大きいので
WebAPI側でJSONを返すようにしたいと思います。

ASP.NET(MVC2)で作成したWebAPIでJSONを返す


以前作成したWebAPIのTestControler.vbのIndexメソッドを変更します。

TestControler.vb
Namespace MvcApplication1
    Public Class TestController
        Inherits System.Web.Mvc.Controller

        <HttpPost()>
        <ValidateInput(False)> _
        Public Function Index(ByVal collection As FormCollection) As JsonResult
             'パラメータとして渡されたID,NAMEを取得
            Dim id As Integer = CInt(collection.Item("id"))
            Dim name As String = collection.Item("name")

            'JSON形式で返す。返せるものはシリアライズ可能なオブジェクト
            Dim lst As New List(Of KeyValuePair(Of Integer, String))
            lst.Add(New KeyValuePair(Of Integer, String)(id, name))

            Return Json(lst)
        End Function

    End Class
End Namespace

WebアプリケーションにデータをPostするhtmlも変更します。
TestMvcApplication1.html
<html>
    <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 </head>

 <body>
  <h2>MvcApplication1テスト</h2>
     <form action="http://localhost:3766/Test" method="post">
      <input type="text" name = "id" value="1" />
      <input type="text" name = "name" value="田中" />
         <input type=submit />
     </form>
 </body>
</html>

実行結果
[{"ID":1,"NAME":"田中"}]

ASP.NET(MVC2)で作成したWebAPIでDataTableのJSONを返す


.NETだったら、DataTableオブジェクトを返したいですよね~
そこでTestControler.vbのIndexメソッドを変更してみました。
    Dim tbl As New DataTable() 
    tbl.Columns.Add("ID", GetType(Integer)) 
    tbl.Columns.Add("NAME", GetType(String)) 
    tbl.Rows.Add(New Object() {id, name}) 
    Return Json(tbl)
TestMvcApplication1.htmlを実行すると、「型 'System.Reflection.Module' のオブジェクトのシリアル化を実行中に循環参照が見つかりました。 」とエラーになりました。
DataTableはJsonにシリアライズできないようです。

DataTableオブジェクトをJSONで返す方法は、きっと他にもあると思いますが今回は「JSON.NET」を使ってみたいと思います。
JSON.NETは.NETのインスタンスをJSONに変換してくれるライブラリです。
以下よりダウンロードします。
http://json.codeplex.com/
ダウンロードした「Json45r8.zip」を解凍します。
解凍してできたフォルダの「Bin」配下より、使用するFrameworkのバージョンフォルダからdllを、ソースコードの「bin」フォルダにコピーします。
※今回は「Json45r8\Bin\Net35\Newtonsoft.Json.dll」を使用します。

それではTestControler.vbのIndexメソッドをJSON.NETを使用した方法に変更してみます。

TestControler.vb
参照設定で先ほどコピーしたNewtonsoft.Json.dllを追加します。
Namespace MvcApplication1
    Public Class TestController
        Inherits System.Web.Mvc.Controller

        <HttpPost()> _
        <ValidateInput(False)> _
        Public Function Index(ByVal collection As FormCollection) As ActionResult
            'パラメータとして渡されたID,NAMEを取得
            Dim id As Integer = CInt(collection.Item("id"))
            Dim name As String = collection.Item("name")
            'DataTableを作成
            Dim tbl As New DataTable
            tbl.Columns.Add("ID", GetType(Integer))
            tbl.Columns.Add("NAME", GetType(String))
            tbl.Rows.Add(New Object() {id, name})
            'Json.NETを使用して返す。
            Dim jsonstr As String = Newtonsoft.Json.JsonConvert.SerializeObject(tbl, New Newtonsoft.Json.Converters.DataTableConverter())
            Return Content(jsonstr, "application/json")

        End Function

    End Class
End Namespace
TestMvcApplication1.htmlを実行した結果
[{"ID":1,"NAME":"田中"}]

AndroidでJSONを解析する。


Android側のコードです。
JSONを解析するにはJSONArrayやJSONObjectを使用します。
package com.example.helloandroid.activity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

import com.example.helloandroid.R;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    } 

    public void button1Click(View view) {
        //DefaultHttpClientを生成   
        HttpClient httpClient = new DefaultHttpClient();   
        //HttpPostを生成   
        HttpPost req = new HttpPost("http://IPアドレス:ポート番号/AndroidTest/Test");   
        //パラメータ作成   
        List<NameValuePair> params = new ArrayList<NameValuePair>(1);   
        params.add(new BasicNameValuePair("ID", "1"));   
        params.add(new BasicNameValuePair("NAME", "田中"));   
        //リクエスト   
        String strJson = "";   
        try {    
         req.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));   
         HttpResponse res = httpClient.execute(req);   
         int status = res.getStatusLine().getStatusCode();   
         if (status == HttpStatus.SC_OK) {   
          strJson = EntityUtils.toString(res.getEntity());   
         } else {   
           Toast.makeText(this, "接続失敗" + String.valueOf(status), Toast.LENGTH_LONG).show();
           return;
         }   
        } catch (Exception e) {   
           e.printStackTrace();   
        }   
        //Jsonを解析
        try {
            JSONArray element = new JSONArray(strJson);
            for (int i = 0; i < element.length(); i++) {
                JSONObject jsonObject = element.getJSONObject(i); 
                Toast.makeText(this, jsonObject.getString("NAME"), Toast.LENGTH_LONG).show();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }
    

}

0 件のコメント: