#PowerAutomate #LogicApp で動的なプロパティ名を持つ JSON を扱う方法

Microsoft Graph API で Planner のタスクに含まれるチェックリストの情報が取得できます。

しかし…取得した JSON が非常に扱いづらかった！
そんなことを悲観してたら、フォロワーの皆様からご助言を頂いて扱いやすい形まで加工できたので、その知見を共有したいと思います。

## 事の始めはこのツイートから

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">MS Graph の Planner task detail の checklistitems ってむずいな。<br>Array じゃないんだもん…<br><br>Power Automate でごにょごにょするときに json schema が定まらないから、どうするべかなぁ<a href="https://t.co/RvH3yazfbJ">https://t.co/RvH3yazfbJ</a></p>&mdash; SP.Restaurant.js (@SpRestaurant) <a href="https://twitter.com/SpRestaurant/status/1229778005435678721?ref_src=twsrc%5Etfw">February 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## Planner task detail の checklist を確認する

下記のタスクを Microsoft Graph エクスプローラーから取得します。

GET https://graph.microsoft.com/v1.0/planner/tasks/{task-id}/details

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/70230ef5-2cc6-35ae-db25-59a8b4b9a574.png)

```json

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#planner/tasks('iiZ7Fq6FFkqIXS6i8bR6IvoAG6Ic')/details/$entity",
    "@odata.etag": "W/\"JzEtVGFza0RldGFpbHMgQEBAQEBAQEBAQEBAQEBAYCc=\"",
    "description": "ここにメモを書きます",
    "previewType": "automatic",
    "id": "iiZ7Fq6FFkqIXS6i8bR6IvoAG6Ic",
    "references": {},
    "checklist": {
        "37396": {
            "@odata.type": "#microsoft.graph.plannerChecklistItem",
            "isChecked": true,
            "title": "チェックリスト２",
            "orderHint": "85861956244X",
            "lastModifiedDateTime": "2020-02-18T16:47:50.1702791Z",
            "lastModifiedBy": {
                "user": {
                    "displayName": null,
                    "id": "6742f833-5b42-43b4-b673-f7530e236689"
                }
            }
        },
        "60542": {
            "@odata.type": "#microsoft.graph.plannerChecklistItem",
            "isChecked": false,
            "title": "チェックリスト３",
            "orderHint": "858619562420",
            "lastModifiedDateTime": "2020-02-18T16:47:49.3421666Z",
            "lastModifiedBy": {
                "user": {
                    "displayName": null,
                    "id": "6742f833-5b42-43b4-b673-f7530e236689"
                }
            }
        },
        "66123": {
            "@odata.type": "#microsoft.graph.plannerChecklistItem",
            "isChecked": false,
            "title": "チェックリスト１",
            "orderHint": "8586195624826666382Pw",
            "lastModifiedDateTime": "2020-02-18T16:47:42.9828025Z",
            "lastModifiedBy": {
                "user": {
                    "displayName": null,
                    "id": "6742f833-5b42-43b4-b673-f7530e236689"
                }
            }
        }
    }
}
```

## Planner task detail の checklist が扱いづらい点

- checklist が動的なプロパティ名(*)を持つオブジェクトであること
- checklist が配列ではなくオブジェクトであること

(*) 上記の例でいうと "37396", "60542", "66123" の部分を指します

```json
{
  "37396": { //省略 },
  "60542": { //省略 },
  "66123": { //省略 }
}
```

## Planner task detail の checklist を扱いやすくするためには

- checklist を配列にする
- プロパティ名を固定にする（例として下記のような形式） 

checklist の JSON を下記のように加工できれば扱いやすいデータと言えます
このデータに加工するための手順は次の通りです

```json
[
  { "id": "37396", "value": { //省略 } },
  { "id": "60542", "value": { //省略 } },
  { "id": "66123", "value": { //省略 } }
]
```

## checklist の加工手順

　 1. ckecklist をプロパティ値に持つオブジェクトに加工します（プロパティ名は "root"）

```json:json
{
  "root": {
    "37396": { //省略 },
    "60542": { //省略 },
    "66123": { //省略 }
  }
}
```

　2. json 形式を xml 形式に変換します（要素名の先頭が数字の場合、Unicode16進数にエンコードされます）

```xml:xml
<root>
  <_x0033_7396><省略></_x0033_7396>
  <_x0036_0542><省略></_x0036_0542>
  <_x0036_6123><省略></_x0036_6123>
</root>
```

　3. root 要素の子要素の名前を抽出します（ここで配列に変換されます）

```json:json
[
  "_x0033_7396",
  "_x0036_0542",
  "_x0036_6123"
]
```

　4. 各項目を文字列操作して、xml タグっぽく加工します

```json:json
[
  "<_x0033_7396></_x0033_7396>",
  "<_x0036_0542></_x0036_0542>",
  "<_x0036_6123></_x0036_6123>"
]
```

　5. コレクション関数 join を使って文字列操作して、親要素に `<root>` を持つ xml に加工します

```xml:xml
<root>
  <_x0033_7396></_x0033_7396>
  <_x0036_0542></_x0036_0542>
  <_x0036_6123></_x0036_6123>
</root>
```

　6. 手順2とは逆で、xml 形式を json 形式に変換して、root の値を取得します（Unicode16進数がデコードされます）

```json:json
{
  "37396": "",
  "60542": "",
  "66123": ""
}
```

以上の手順を踏んで、動的プロパティの値を空文字にすることができたので、残りは愚直に文字列操作して動的プロパティの配列を取得します

　7. 先頭と末尾の括弧を削除して、カンマ区切りで split して、末尾の `: ""` を削除します

```json:json
[
  "37396",
  "60542",
  "66123"
]
```

　8. ckecklist のプロパティ名が取得できたので、ckecklist オブジェクトに対して、プロパティ名を指定して値を取得します
　   選択アクションを使って加工します

|id|value|
|:---|:---|
| item()|outputs('作成')?['checklist']?[item()]|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/c5769788-8986-d234-1d40-dc8d8e2aee59.png)

　9. 最終結果がこちら

```json
[
  {
    "id": "37396",
    "value": {
      "isChecked": true,
      "title": "チェックリスト２",
      "orderHint": "85861956244X",
      "lastModifiedDateTime": "2020-02-18T16:47:50.1702791Z",
      "lastModifiedBy": {
        "user": {
          "displayName": null,
          "id": "6742f833-5b42-43b4-b673-f7530e236689"
        }
      },
      "@odata.type": "#microsoft.graph.plannerChecklistItem"
    }
  },
  {
    "id": "60542",
    "value": {
      "isChecked": false,
      "title": "チェックリスト３",
      "orderHint": "858619562420",
      "lastModifiedDateTime": "2020-02-18T16:47:49.3421666Z",
      "lastModifiedBy": {
        "user": {
          "displayName": null,
          "id": "6742f833-5b42-43b4-b673-f7530e236689"
        }
      },
      "@odata.type": "#microsoft.graph.plannerChecklistItem"
    }
  },
  {
    "id": "66123",
    "value": {
      "isChecked": false,
      "title": "チェックリスト１",
      "orderHint": "8586195624826666382Pw",
      "lastModifiedDateTime": "2020-02-18T16:47:42.9828025Z",
      "lastModifiedBy": {
        "user": {
          "displayName": null,
          "id": "6742f833-5b42-43b4-b673-f7530e236689"
        }
      },
      "@odata.type": "#microsoft.graph.plannerChecklistItem"
    }
  }
]
```

## PowerAutomate フロー詳細

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/f29599de-2ab5-cd01-e180-4fcf9e773b67.png)

## 最後に

今回の検証のキッカケと様々なアドバイスを頂きました皆様にお礼を申し上げます

- [@SpRestaurant](https://twitter.com/SpRestaurant)さん
- [@twit_ahf](https://twitter.com/twit_ahf)さん
- [@mofumofu_dance](https://twitter.com/mofumofu_dance)さん（Qiita：https://qiita.com/h-nagao）

やり取りした Twitter スレッドはこちらです

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">json帰ってきてるけど気合いのsplit案件か。。 <a href="https://t.co/GdcTzXBDwt">https://t.co/GdcTzXBDwt</a></p>&mdash; Hiro (@mofumofu_dance) <a href="https://twitter.com/mofumofu_dance/status/1229908569161494528?ref_src=twsrc%5Etfw">February 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 参考
[Getting JSON keys in flow](https://powerusers.microsoft.com/t5/General-Power-Automate/Getting-JSON-keys-in-flow/td-p/99743)
[Power Automateでの"LookUp"](https://qiita.com/h-nagao/items/0ccd5bf291605cc9a622)
[#PowerAutomate の"LookUp" 番外編 (compose json dictionary)](https://qiita.com/h-nagao/items/25fb21d7133e25c07a34)
[https://github.com/ahf0124/LogicFlow-ja/tree/master/EnumJsonKeys](https://github.com/ahf0124/LogicFlow-ja/tree/master/EnumJsonKeys)