Power Automate で作成した JSON ファイルを読み込む時の注意点

久しぶりの Power Automate ネタです。


# はじめに

Power Automate のワークフローで作成した SharePoint ドキュメント ライブラリ上の JSON 形式のファイルを別の Power Automate のワークフローでそのファイルを読み込んで[「JSON の解析 (ParseJson)」アクション](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-workflow-actions-triggers?WT.mc_id=DX-MVP-5003113#parse-json-action)を実行するとエラーとなってしまうという状況に遭遇しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/22d4eccb-fc57-e604-1e9f-221c9e118f04.png)

> エラーの詳細
> 'ParseJson' という種類のアクションの 'content' プロパティは有効な JSON である必要があります。指定された値を解析できません: 'Unexpected character encountered while parsing value: ﻿. Path '', line 0, position 0.'。

パッと見、正しい JSON 形式で書かれている見えるのになぜこのようなエラーが発生するのか、よく分からずちょっと悩みました。


# JSON は正しく作られているっぽいが...

実行履歴の「JSON の解析 (ParseJson)」アクションにある「コンテンツ」の値をコピーして、[JSON 整形ツール](https://tools.m-bsys.com/development_tooles/json-beautifier.php)にペーストして整形すると「正しい JSON 形式でした。」と返ってきます。内容的には正しいようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/b13226af-4d33-a7de-8d3a-5c552d237970.png)


# 読み込んだ JSON ファイルの内容は Base64 エンコードされている

実行履歴から「ファイル コンテンツの取得」アクションで JSON ファイルを読み込むと、ファイルの内容が Base64 文字列としてエンコードされる application/octet-stream であることが分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/f6ce5e39-1b1f-29f4-b8ae-5ec6ff88ce86.png)

$content プロパティにファイルの内容が格納されているので、[「作成 (Compose)」アクション](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-workflow-actions-triggers?WT.mc_id=DX-MVP-5003113#compose-action)でこれを抽出して [Base64 文字列をデコード](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference?WT.mc_id=DX-MVP-5003113#base64tostring)してあげる必要があります。

```
base64ToString(outputs('パスによるファイル_コンテンツの取得')?['body']?['$content'])
```

https://powerusers.microsoft.com/t5/General-Power-Automate/Parse-JSON-file-from-OneDrive-for-Business/m-p/46346?WT.mc_id=DX-MVP-5003113


# BOM 付きだと読み込み失敗する？

JSON ファイルの読み込み方は分かりましたが、それでも冒頭のエラーはまだ解決できず、原因を探るため引き続き調べていると、「**BOM 付き**の UTF-8」で作成した JSON ファイルだと「JSON の解析 (ParseJson)」アクションでエラーとなるという情報を見つけました。

https://powerusers.microsoft.com/t5/Building-Flows/Issue-parsing-a-JSON-file-from-OneDrive-for-Business/m-p/481689?WT.mc_id=DX-MVP-5003113

[とほほ WWW 入門の JSON の仕様](https://www.tohoho-web.com/ex/json.html)をチェックすると、「文字コードは UTF-8 固定」で「[バイトオーダーマーク (BOM)](https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88%E9%A0%86%E3%83%9E%E3%83%BC%E3%82%AF) を先頭につけてはならない」とあります。ということで、**JSON 文字列の先頭に BOM が付いている場合「JSON の解析 (ParseJson)」アクションではエラーになる**んだな (JSON の仕様と異なる値を解析しようとするから) と分かりました。

ただ、JSON ファイルを作成しているワークフローでは「BOM 付き」で作成した覚えがありません。実際の「ファイルの作成」アクションを確認してもそのようなオプションもありませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/2954c5bf-61ae-59c6-300d-b9e3529ca711.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/5942711c-2550-1de0-312e-dbf93955d772.png)

念のため、作成した JSON ファイルをバイナリエディターで開いてみると、先頭 3 バイトに見覚えのないゴミ？のような値を見つけました。**この「EF BB BF」という値こそが「BOM」**です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/4792f766-21d2-907b-8bc8-6fabe2616246.png)


# 解決編

**「JSON の解析 (ParseJson)」アクションでエラーになる原因は「JSON 文字列の先頭に BOM が付いていたため」**といことがハッキリと分かりましたので、対策を施していきます。

JSON ファイルを作成する時に BOM を付けない策を施すのは先ほどのスクリーンショットように「BOM を付ける / 付けない」という操作が難しいようなので、JSON ファイルを読み込む時に BOM を取り除くことにしました。

Power Automate で文字コードを表現する関数はいくつかありますが、今回は BOM を [decodeUriComponent 関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference?WT.mc_id=DX-MVP-5003113#decodeuricomponent)を使って以下のように表現しました。

```
decodeUriComponent('%EF%BB%BF')
```

そして、以下のように [replace 関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference?WT.mc_id=DX-MVP-5003113#replace)を使って Base64 デコードした JSON 文字列から BOM を取り除きます。

```
replace(base64ToString(outputs('パスによるファイル_コンテンツの取得')?['body']?['$content']), decodeUriComponent('%EF%BB%BF'), '')
```

これで SharePoint ドキュメント ライブラリ上の JSON 形式のファイルが正常に読み込めるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230264/e7f816f0-ea4b-52f5-1a67-b1656917532d.png)


# まとめ

「JSON の解析 (ParseJson)」アクションを使って JSON 文字列を解析する場合は、以下のような事前準備を行うこと。

- JSON ファイルから読み込んだ Base64 文字列を base64ToString 関数を使ってデコードする
- replace 関数を使って JSON 文字列から BOM を取り除く
- BOM を文字コードで表すには ```decodeUriComponent('%EF%BB%BF')``` と書く