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

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