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 にしておきます
postシート
- 1行目を項目名にしておきます。2行目からはデータが入ってきます
- シート名は post にしておきます
※ 今回は便宜上postとgetのパラメータを同じにしています。
スクリプトを作成
スプレッドシートのメニューで、ツール > スクリプトエディタ... を選択します。その後、プロジェクト名、ファイル名をそれぞれ適宜設定します。
/**
* 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 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);
}
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からスプレッドシートを利用するには、オーソライズが必要なので、まずは、下記のように実行して権限を取得します。
APIを公開する
下記の手順で公開します。とりあえずスクショをぺたぺた貼っていきます。
新しい版(APIのversionになります)を登録
ウェブアプリとして導入
※ 公開したいバージョンを選択、アプリケーションの実行ユーザは Meにしておいて、アクセスできるユーザーは、**全員(匿名ユーザーを含む)**にしておきます。
最後に出てきた画面のURLをコピーして置きます。
iOSアプリ側
ソースを落とす
$ git clone git@github.com:mitolog/GASEasyAPI-alamofire-client-sample.git GASEasyAPIAlamoSmaple
$ cd GASEasyAPIAlamoSmaple
$ pod install
さっきコピーしておいた、urlをコピペ
下記の部分になります。
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のプロジェクトに入れてアプリのテンプレートとして持っとくと使い回しできて良いのかも