59
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-05-02

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
59
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?