Blue Prism で JSON を扱う

はじめに
-------------------

Blue Prism には、「連想配列（ハッシュ/辞書）」データ型は用意されていません。
JSON を扱うには、「配列」と「連想配列」が必要ですが、Blue Prism ではどのようにして対応することができるのか、調べてみました。


JSON をパースする
--------------------

今回サンプルとして扱う JSON は下記です。GMail API の [Users.messages: list](https://developers.google.com/gmail/api/v1/reference/users/messages/list) のレスポンスbodyを使いました。

``` json
{
    "messages":[
        {
            "id":"1702fb0a2b9041c2",
            "threadId":"1702fb0a2b9041c2"
        },
        {
            "id":"17014c9439dae1bc",
            "threadId":"17014c9439dae1bc"
        }
    ],
    "resultSizeEstimate":2
}
```

Blue Prism をインストールするとついてくる、```Utility - JSON``` という VBO に関連のアクションがありそうですので、使ってみます。

<img width="568" alt="00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/9c7fee00-7c04-7cb6-69c1-29e15fab4c76.jpeg">


図中の ```A``` で、```Utility - JSON::JSON to Collection``` を使って、JSON文字列からコレクションの変換を図っています。
その結果得られたコレクションは下記のような構造になっています。

<img width="513" alt="01.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/44d9aa3e-8d0b-06a1-e167-312fec3c517d.jpeg">


* JSON の第一階層のKey である、"messages", "resultSizeEstimate" が列として認識されています。
* "resultSizeEstimate" は JSON上で値が数字の ```2``` であったため、コレクション上の "resultSizeEstimate" 列のタイプも「数値」型で、行の値も ```2``` になっています。
* 一方で "messages" は JSON上で値が配列（「キーが ```id```, ```threadId``` の連想配列」の配列）だったため、コレクション上の "messages" 列のタイプも「コレクション」型で、行の値は、```2行``` と省略表記されています。

ちなみに、「2行」と書かれたリンクっぽいところをクリックするとエラー画面が表示されます。

<img width="511" alt="02.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/2b71aeee-f04c-5d09-e3f2-a560fbd8c678.jpeg">

この「2行」と書かれた値の正体はなんでしょうか？

計算ステージで message列に入っていたデータを ```messages``` コレクションに値を取り出してみます。

<img width="602" alt="03.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/ef8a8120-6b2e-4e62-4859-787d30d78062.jpeg">


すると、下記のようなデータになっていることがわかります。
* 列名は ```JSON:Array``` で、「コレクション」型
* 値は二行入っており、 ```計1行の1``` と書かれている。（同じようにリンクっぽく書かれているが、クリックするとエラー画面が表示されます）

<img width="514" alt="04.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/60ea919b-c201-671a-5061-19596ee990cf.jpeg">

* コレクションは事前定義なく列を複数使えるので、「一行だけのコレクション」を「連想配列」として利用しているのですね。もし、Blue Prism に連想配列型のデータ構造があれば、ここは「コレクション」型ではなく「連想配列」型と表示されたと思います。

このデータについて「繰り返しステージ」を使って個別に行のデータを取り出してみます。下記はデータの取り出しを行っている計算ステージです。（フロー図の「B」）
※ 一風変わった列名なので戸惑いますが、 ```[messages.JSON:Array]``` と指定すれば動きます。

<img width="590" alt="05.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/777d6ee1-8538-f730-c1be-6ae8fb3c4776.jpeg">

取り出したデータの構造はこちらです。こちらについても、1行のみのコレクション型データを連想配列として使っている様子が伺えます。

<img width="513" alt="06.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/f2f61e39-7ac4-3afc-973a-6dec4321df13.jpeg">


JSON をパースする際のまとめ
--------------------------------
* ```Utility - JSON::JSON to Collection``` を使うと、JSON文字列を Blue Prism 上で扱うことができるデータ構造に変換できる
* JSON の連想配列は、Blue Prism 上では 1行のみのコレクション型データとして扱う


JSON を組み立てる
----------------------

Blue Prism のデータアイテムやコレクションを使って、JSON を組み立ててみます。

パースの際に使った JSON と同じもの（GMail API の [Users.messages: list](https://developers.google.com/gmail/api/v1/reference/users/messages/list) のレスポンスbody）を作ってみます。

``` json
{
    "messages":[
        {
            "id":"1702fb0a2b9041c2",
            "threadId":"1702fb0a2b9041c2"
        },
        {
            "id":"17014c9439dae1bc",
            "threadId":"17014c9439dae1bc"
        }
    ],
    "resultSizeEstimate":2
}
```

まず目的の JSON と同じ内容のコレクションを作成し、```Utility - JSON::Collection to JSON``` （下図「C」）を使って JSON に変換する流れで作成できそうです。

<img width="494" alt="10.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/ad737d3f-53d8-16ec-5951-d43401d890ca.jpeg">



最終的に JSON に変換するためのコレクションを ```Target ``` という名前で用意します。列名は下記の通りです。

<img width="514" alt="11.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/1b7a4119-53a0-938b-fc37-582bfb677774.jpeg">


1行だけのデータを現在地として用意し、それを連想配列とみなして```Utility - JSON::Collection to JSON```に渡す流れです。

次に、messages として二件のデータをコレクション ```message list``` として用意します。

<img width="514" alt="12.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/94e9b5bf-a509-37d3-5d87-22d3d55eab42.jpeg">


```message list``` を、```Target``` の messages列に設定します。（フロー図の「A」）

<img width="644" alt="13.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/13bc0b3f-1c06-8e32-cc1d-96194cc4ca2a.jpeg">


同じように、```message list```の行数を数えたデータアイテム ```カウント``` を、```Target``` の resultSizeEstimate列に設定します。

<img width="640" alt="14.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564576/4707fae0-b725-99c9-9d44-c018f94c67b4.jpeg">


```Target``` の内容が、目的とする JSON と同じ内容に設定できたので、```Utility - JSON::Collection to JSON``` を呼びます。（フロー図の「C」）

得られた結果は下記になりました。

``` json
[
    {
        "messages":[
            {
                "id":"id0",
                "threadId":"threadId0"
            },
            {
                "id":"id1",
                "threadId":"threadId1"
            }
        ],
        "resultSizeEstimate":"2"
    }
]
```
一番外側が、配列になっていますね。。。
結果としては正しいですが、ほしい形のJSONは得られませんでした。

JSON を組み立てる際のまとめ
--------------------------------
Blue Prism が連想配列のデータタイプを、1行のコレクションとして扱っているためか、本来JSONのオブジェクトとして表現したいデータが、配列に囲まれてしまうことがわかりました。
うまいやり方をご存知の方がいらっしゃったら、コメント等で教えていただけるとありがたいです！


追記
-------------------------------

Blue Prism に機能追加要望を出せるとのことなので、 [「Dictonary型のデータアイテムを追加して欲しい」](https://community.blueprism.com/ideas/ideas/viewidea?IdeationKey=497038c3-87a2-499e-aa23-d54d69e385e2) というリクエストを登録してみました。