UnityからkintoneのREST APIを叩く方法

# はじめに
Unityからウェブデータベースにアクセスしたい！というシチュエーション、ありますよね。

UIが整っているウェブデータベースは非エンジニアでもデータの管理が可能なため、エンジニアと非エンジニアが同じプロジェクトに関わっている場合はとても便利です。

この記事では非エンジニアでもデータの入力や編集がしやすかったり、データベースの構造が容易に変更できるkintoneにUnity内からアクセスする方法を紹介します。

![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/63056d87-1db8-7948-1f5e-1a207397f7a2.png)


Unity初心者なので、何かツッコミがありましたら遠慮なくお願いします。

# kintone環境
無料の開発者ライセンスを[こちらのページ](https://developer.cybozu.io/hc/ja/articles/200720464)から入手することができます。
すぐに手に入るので、この環境をもとに記事のサンプルコードを試してみてください。
kintone内のアプリの作り方やアプリIDの確認方法については色々と記事は出ているので、ググってください。

# 認証
Unityからkintoneにアクセスする際は：
- パスワード認証
- APIトークン認証
のいずれかの認証方法が簡単なので、お勧めします。

認証についてはこちらを参照してください：
https://developer.cybozu.io/hc/ja/articles/201941754#step7

# 使用するフレームワーク
## SimpleJSON
kintoneアプリ(ウェブデータベース)内のレコード情報を取得するためにREST APIを叩くと、ネストが深くて複雑なJSONが返ってきます。このJSONの形はkintoneアプリの作り方によっては全然違います。C#ではあらかじめどんな形のレスポンスが返ってくるのかをスクリプト内のクラスで定義する必要がありますが、kintoneのフォームを変更するとこのクラスの内容も変更する必要があるので、とても面倒くさいです。

この問題を解決するためにSimple JSONというフレームワークを使います。

SimpleJSONは非常に使いやすいフレームワークで、REST APIを叩くのに必要なUnityWebRequestで返ってきたJSONをJSONNodeという型に入れることで容易にJSON内のデータにアクセスすることができます。

## 設定方法
設定方法は簡単です：

1. SimpleJSONのコードを[Community Wiki](https://wiki.unity3d.com/index.php/SimpleJSON)からコピーし、SimpleJSON.cs という名前で保存します
2. Unityプロジェクト内の『assets』フォルダ内の『plugins』フォルダ(無かったら作る)にSimpleJSON.csを配置します

<img width="381" alt="simplejsoninfolder.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/d58b470c-70ba-5185-8cd0-c2ed43186efb.png">
3. スクリプト内に using SimpleJSON; を定義します

これだけです。

## 使い方
kintoneのREST APIを叩いて、下記のようなJSONレスポンスが返ってきたとします：

```json
{
    "records": [
        {
            "recordID": {
                "type": "RECORD_NUMBER",
                "value": "1"
            },
            "mychoice": {
                "type": "DROP_DOWN",
                "value": "おめがレイ"
            }
        },
        {
            "recordID": {
                "type": "RECORD_NUMBER",
                "value": "2"
            },
            "mychoice": {
                "type": "DROP_DOWN",
                "value": "おめがリオ"
            }
        }
    ],
    "totalCount": "2"
}
```
このJSONの中の『おめがレイ』と『おめがリオ』という値は下記のようにstring型として取得ができます：

```cs
string JSONstring = request.downloadHandler.text;
JSONNode KintoneResponse = JSON.Parse(JSONstring);
var FirstAnswer = KintoneResponse["records"][0]["mychoice"]["value"].Value;
var SecondAnswer = KintoneResponse["records"][1]["mychoice"]["value"].Value;
```

# REST APIの叩き方
StartCoroutineメソッドを呼び、yield return文を使ってREST APIを叩き、callbackでJSONレスポンスを用いた処理をします。

下記のサンプルコードでは、kintone内のアプリに対してAPIを叩き、全てのレコードの情報を取得しています(100件以上レコードがある場合は100件まで取得します)。
レコードの取得後、1件目のレコードの中の『mychoice』というフィールドコードを設定したフィールドに保存された値をコンソールに出力しています。
{サブドメイン名}、{アプリID}、{APIトークン}は自分の環境に合わせて正しい値を設定してください。

```testAPI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using SimpleJSON;

public class testAPI : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(
            getKintoneRecords(
                (JSONNode JSONresponse) => 
                {
                    HandleAPIresponse(JSONresponse);
                }
            )
        );
    }

    private IEnumerator getKintoneRecords(System.Action<JSONNode> callBack)
    {
        //APIのURI、HTTPメソッド、ヘッダーの設定
        string RequestURL = "https://{サブドメイン名}.cybozu.com/k/v1/records.json?app={アプリID}";
        UnityWebRequest request = UnityWebRequest.Get(RequestURL);
        request.SetRequestHeader("X-Cybozu-API-Token", "{APIトークン}");

        //APIのリクエストを送信
        yield return request.SendWebRequest();

        //レスポンスをJSONNode型に格納
        string JSONstring = request.downloadHandler.text;
        JSONNode JSONnode = JSON.Parse(JSONstring);

        //JSONNode型のレスポンスをcallBackに渡す
        callBack(JSONnode);
    }

    private void HandleAPIresponse(JSONNode APIresponse)
    {
        //コールバック関数内でAPIリクエストで返されたレスポンスの処理を行う
        string KintoneData = APIresponse["records"][0]["mychoice"]["value"].Value;
        Debug.Log("Data from kintone is:" + KintoneData);
    }
}
```
# コード解説

まず、StartCoroutineメソッドを実行します。
getKintoneRecords関数を呼び、この関数の中のyield return文でREST APIを叩きます。REST APIのレスポンスはJSONNode型のJSONresponseという変数に格納され、この変数をそのままHandleAPIresponse関数で処理をします。

```cs
    void Start()
    {
        StartCoroutine(
            getKintoneRecords(
                (JSONNode JSONresponse) => 
                {
                    HandleAPIresponse(JSONresponse);
                }
            )
        );
    }
```

getKintoneRecords関数の中でREST APIを叩く処理を書きます。
REST APIのレスポンスで続けて処理を行いたい場合はコールバックを使用するので、このように宣言します。

```cs
    private IEnumerator getKintoneRecords(System.Action<JSONNode> callBack)
    {
        //REST APIを叩く処理
    }
```

kintoneのREST APIを叩く際に、ヘッダーに認証情報が必要です。
APIトークン認証を使用する際は[アプリからAPIトークンを生成](https://developer.cybozu.io/hc/ja/articles/202463840)し、下記のようにヘッダー情報を付与します。

```cs
request.SetRequestHeader("X-Cybozu-API-Token", "{APIトークン}");
```

APIトークン認証ではなくユーザ認証を使用したい場合、下記のように宣言します

```cs
request.SetRequestHeader("X-Cybozu-Authorization", "{『ユーザ名:パスワード』をBASE64エンコードした文字列}");
```

yield return文でREST APIを叩きます。
レスポンスが返ってくるまで、次の行には進まないようになっています。

```cs
yield return request.SendWebRequest();
```

レスポンスをJSONNode型の変数に格納し、次の関数で使えるようにします。
JSONNode型はSimpleJSONによって作られた型です。

```cs
//レスポンスをJSONNode型に格納
string JSONstring = request.downloadHandler.text;
JSONNode JSONnode = JSON.Parse(JSONstring);

//JSONNode型のレスポンスをcallBackに渡す
callBack(JSONnode);
```

最後に、コールバック関数内でREST APIのレスポンスを活用した処理を行います。

```cs
private void HandleAPIresponse(JSONNode APIresponse)
    {
        //コールバック関数内でAPIリクエストで返されたレスポンスの処理を行う
        string KintoneData = APIresponse["records"][0]["mychoice"]["value"].Value;
        Debug.Log("Data from kintone is:" + KintoneData);
    }
```

# 参考になる記事
| 使用するkintone REST API | Qiita記事 |
|:------------------------:|-----------|
| [レコードの一括取得](https://developer.cybozu.io/hc/ja/articles/202331474#step2)       | [kintoneアプリに溜めたゲームスコア情報をUnity内に表示させる](https://qiita.com/will-yama/items/489b1f411e59bc95af26)    |
| [レコードのステータス更新](https://developer.cybozu.io/hc/ja/articles/204791550) | [Unityからkintoneアプリのレコードを承認する方法](https://qiita.com/will-yama/items/f76ad908df36e9d4626f)    |