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のプロジェクトに入れてアプリのテンプレートとして持っとくと使い回しできて良いのかも
 










