スプレッドシートとgoogle apps scriptで簡易APIを作ってalamofireからget/postする

More than 3 years have passed since last update.

google apps scriptにはContent Serviceというクラスがあって、GUIを伴うwebアプリケーションを作れたり、REST APIを作れたりします。今回は、GET/POSTができる簡易的なAPIを作って、alamofireとスプレッドシート間でjsonデータのやりとりをしてみたいと思います。

サーバ側がまだ準備できてないとか、サーバ用意するほどのものでもない場合に便利かと思います。


こんな感じ


やりたいこと


  • GET用シートからデータをalamofireで取得

  • POST用シートにデータをalamofire経由で追加

※ 但し、alamofireからのpost時に画像は含められません(ContentServiceがmulti-partに非対応のため)


ソース

[google apps script]

https://github.com/mitolog/GASEasyAPI

[iOS]

https://github.com/mitolog/GASEasyAPI-alamofire-client-sample


手順


スプレッドシートを作成

下記の感じで作成します。


getシート


  • 1行目を項目名にして、2行目からデータを入れます

  • シート名は get にしておきます

Screen Shot 2015-05-02 at 14.14.11.png


postシート


  • 1行目を項目名にしておきます。2行目からはデータが入ってきます

  • シート名は post にしておきます

Screen Shot 2015-05-02 at 16.44.38.png

※ 今回は便宜上postとgetのパラメータを同じにしています。


スクリプトを作成

スプレッドシートのメニューで、ツール > スクリプトエディタ... を選択します。その後、プロジェクト名、ファイル名をそれぞれ適宜設定します。


Get.gs

/**

* Get API
* @return json object
*/

function doGet(e) {

var getSheet = getFirstMatchedFileAndSheet(g_filename, g_getSheetName);
if(!getSheet) return;

// First row must be parameter names
var cells = getSheet.getDataRange().getValues();
var paramNames = [];
if(!cells || cells.length <= 1){
return;
}

paramNames = cells[0];
cells.shift();

var userLists = [];
cells.forEach(function(aLine, idx){
var aDic = {};
aLine.forEach(function(elem, elemIdx){
aDic[paramNames[elemIdx]] = elem;
});
userLists.push(aDic);
});

var result = {};
result['data'] = userLists;

return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);

}



Post.gs

/**

* Post API
* @return json object
*/

function doPost(e) {

if(!e) return;

var paramStr = e.postData['contents'];
// debug
// var paramStr = '{"Users": [{"id": "1", "created": "2015-05-02 07:32:01 +0000", "name": "人造人間1号"},{"id": "2", "created": "2015-05-02 07:32:01 +0000", "name": "人造人間2号"}]}';
var params = JSON.parse(paramStr);

var targetSheet = getFirstMatchedFileAndSheet(g_filename, g_postSheetName);
if(!targetSheet) return;

// First row must be parameter names
var dataRng = targetSheet.getDataRange();
var cells = dataRng.getValues();
if(!cells || cells.length < 1){
return;
}

// Make data array[][] to plot spreadsheet range
var paramNames = cells[0];
var dataAry = [];
params["Users"].forEach(function(aParamDic, idx){
var plotLine = [];
paramNames.forEach(function(paramName, pnIdx){
var val = aParamDic[paramName];
plotLine[pnIdx] = (val) ? val : "";
});
dataAry.push(plotLine);
});

// Append data after last data line
dataRng.offset(dataRng.getNumRows(),0,dataAry.length).setValues(dataAry);

var result = {};
result['data'] = dataAry;

return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);

}



Common.gs

var g_filename = 'GASAPIDemo';

var g_getSheetName = 'get';
var g_postSheetName = 'post';
var g_mimeTypeContainStr = 'spreadsheet';

/**
* Driveの中から最初に見つかった、targetFileNameのスプレッドシートを取得する
* @return SpreadSheet
*/

function getFirstMatchedSpreadSheet(targetFileName)
{
var resFile = null;

var files = DriveApp.getFilesByName(targetFileName);
while (files.hasNext()) {
var file = files.next();
if(file.getMimeType().indexOf(g_mimeTypeContainStr) != -1){
resFile = file;
break;
}
}
return SpreadsheetApp.open(resFile);
}

/**
* Driveの中から最初に見つかった、filenameファイルのsheetnameシート取得する
* @return Sheet
*/

function getFirstMatchedFileAndSheet(filename, sheetname)
{
var targetFile = getFirstMatchedSpreadSheet(filename);
if(!targetFile){
return null;
}

var targetSheet = targetFile.getSheetByName(sheetname);
if(!targetSheet){
return null;
}
return targetSheet;
}



アプリの実行権限を得る

Google Apps Scriptからスプレッドシートを利用するには、オーソライズが必要なので、まずは、下記のように実行して権限を取得します。

Screen Shot 2015-05-02 at 15.56.31.png

Screen Shot 2015-05-02 at 15.56.44.png

Screen Shot 2015-05-02 at 15.57.06.png


APIを公開する

下記の手順で公開します。とりあえずスクショをぺたぺた貼っていきます。


新しい版(APIのversionになります)を登録

Screen Shot 2015-05-02 at 17.43.47.png

Screen Shot 2015-05-02 at 17.44.05.png


ウェブアプリとして導入

Screen Shot 2015-05-02 at 17.44.22.png

Screen Shot 2015-05-02 at 17.44.34.png

公開したいバージョンを選択、アプリケーションの実行ユーザは Meにしておいて、アクセスできるユーザーは、全員(匿名ユーザーを含む)にしておきます。

Screen Shot 2015-05-02 at 17.44.50.png

最後に出てきた画面のURLをコピーして置きます。


iOSアプリ側


ソースを落とす

$ git clone git@github.com:mitolog/GASEasyAPI-alamofire-client-sample.git GASEasyAPIAlamoSmaple

$ cd GASEasyAPIAlamoSmaple
$ pod install


さっきコピーしておいた、urlをコピペ

下記の部分になります。


ViewController.swift

struct AppConsts {

struct HttpGetUrl {
static let UserList = ""
}

struct HttpPostUrl {
static let RegUser = ""
}
}


以上!


感想 & 注意点


  • multipartのpostもできたら尚良いな

  • APIの公開urlはredirectされているので、AFNetworkingとかAlamofire以外で独自でやる際はredirect処理を忘れずに

  • iOS側でエラーがかえってくる場合、jsonのパースで落ちる場合は、スプレッドシートの処理がおかしい可能性があるので、function doPost(e)のeにダミーの値をいれてためすといいです。

  • eの内部構造が公式ドキュメントで解説されていない?ので、困った...(Event Objectのページにも無いし...)

  • realmとかcoredataとかのモデル部分もXcodeのプロジェクトに入れてアプリのテンプレートとして持っとくと使い回しできて良いのかも