この記事はWeb API Advent Calendar 2021の4日目の記事です。
3日目は @makokeさんの[音声認識] Webブラウザの音声認識APIを使うでした!
概要
Power Automate for desktopからWeb APIを利用するとき、「JSONをカスタムオブジェクに変換」アクションを使うことがあります。しかし、null値を含んだJSONをそのまま変換するとうまくカスタムオブジェクトとして扱えません。そこでnullを含むさまざまなJSONに対応できるようにする方法を紹介します。
{
"a": 1,
"b": 2,
"c": null
}
注意
- 2021年12月の記事です。
- Power Automate for desktopでしか役に立たないかもしれません。
- 100%の解決方法ではありません。
- すでに使いこなしているかた向けの記事ではありませんが、Web APIを利用したことがありJSONとカスタムオブジェクトに触れたことのあるかたを対象にしています。
- バージョンは執筆時点で2.14.217.21314です。
- 記事の内容はすべて試していますが公式の見解とは異なる可能性があります。
- コードはコピペで試すことができます。
- 誤りや、より良い方法がありましたらコメントでご指摘いただけると幸いです。
null値のあるJSONをカスタムオブジェクト型にしてみる
JSONはテキスト型のデータ形式です。Power Automate for desktopでデータとして扱えるようにするには「JSONをカスタムオブジェクトに変換」アクションを使います。
見た感じは問題なく認識しているように見えます。
しかし・・・・
変数の設定を使ってカスタムオブジェクト内のcの値を参照してみます。
エラーがでます。
Power Automate for desktopのカスタムオブジェクトではnullが上手く扱えないようです。
cの値が空になっているように見えますが、よく見ると何か出ています。
JsonAsCustomObject['c'].JsonAsCustomObject['c']が空というよくわからない状態です。
ここまでのコード
SET SampleJson1 TO $'''{
\"a\": 1,
\"b\": 2,
\"c\": null
}'''
Variables.ConvertJsonToCustomObject Json: SampleJson1 CustomObject=> JsonAsCustomObject
SET NewVar TO JsonAsCustomObject['c']
解決策ぽいけど?
Power Automate for desktopにとってJSONは文字列です。そこでカスタムオブジェクトへ変換する前でnull値を空白文字に置き換えてしまえば良いわけです。
JSONでの空白文字はダブルクオーテーション2個で表現できます。
「テキストを置換する」アクションでnullを""に置換します。
置換した変数%Replaced%をカスタムオブジェクトに変換します。
値を参照してもエラーなく、カスタムオブジェクトになっているようです。
ここまでのコード
SET SampleJson1 TO $'''{
\"a\": 1,
\"b\": 2,
\"c\": null
}'''
Text.Replace Text: SampleJson1 TextToFind: $'''null''' IsRegEx: False IgnoreCase: False ReplaceWith: $'''\"\"''' ActivateEscapeSequences: False Result=> Replaced
Variables.ConvertJsonToCustomObject Json: Replaced CustomObject=> JsonAsCustomObject
SET NewVar TO JsonAsCustomObject['c']
そんな置換で大丈夫か?
せっかくなのでWeb APIで試します。
「JSONPlaceholder」というフリーのテスト用APIを叩いてみます。
https://jsonplaceholder.typicode.com/
掲示板的な形式の擬似データにGETしてみます。
こういう自由に練習できるサービスはありがたいです!
このようなかたちでレスポンスが返ってきます。
null値は無いようですが、これを先ほどの置換アクションを挟んでカスタムオブジェクトに変換してみます。
コード
Web.InvokeWebService.InvokeWebService Url: $'''https://jsonplaceholder.typicode.com/posts''' Method: Web.Method.Get Accept: $'''application/json''' ContentType: $'''application/xml''' ConnectionTimeout: 30 FollowRedirection: True ClearCookies: False FailOnErrorStatus: False EncodeRequestBody: True UserAgent: $'''Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6''' Encoding: Web.Encoding.AutoDetect AcceptUntrustedCertificates: False ResponseHeaders=> WebServiceResponseHeaders Response=> WebServiceResponse StatusCode=> StatusCode
Text.Replace Text: WebServiceResponse TextToFind: $'''null''' IsRegEx: False IgnoreCase: False ReplaceWith: $'''\"\"''' ActivateEscapeSequences: False Result=> Replaced
Variables.ConvertJsonToCustomObject Json: Replaced CustomObject=> JsonAsCustomObject
おそらくこのような形でエラーが出ると思います。
Path '[1].body', line 12, position 218.がおかしいということなのでWebServiceResponseとReplacedを調べてみます。
投稿文のnullaという単語の一部が置換されてしまいました。
そこでnullが文字の場合を除き、値として「null」の場合だけを選択して置換する必要があります。
選択的置換を考えてみる
一番よいの考えてみます。
JSONにさまざまなnullの出現パターンをつくりnull値のみ置換が可能になるように正規表現をかんがえてみます。
{
"a":null,
"b" : Null,
"c" : null ,
"Checknull": false,
"name" : "janull nulla",
"null_check":true,
"test": "私はnull",
"test1":"null",
"test2":"今日は null ",
"test3": null
}
置換したいnull値の条件を考えます。
必ず先頭にコロン「:」があり、スペースなどの空白文字があったりなかったりした後方に存在します。
スペースなどの空白文字またはカンマ「,」または波括弧「}」の前方に存在します。
スペースなどの空白文字は複数回繰り返される可能性があります。
これらの条件を同時に満たすnullのみを検索できるようにすればいけそうです。
肯定後読み?<=
と肯定先読み?=
を組み合わせて検索条件にしました。
(?<=:\s*)null(?=\s*|,|})
また大文字小文字を無視するように「テキストを置換する」アクションの設定をします。
文字列としてのnullは無視し、null値のみ置換してカスタムオブジェクト型のデータとして扱えるようになりました。
「JSONPlaceholder」でもうまくいきます。
お試しください。
コード
SET SampleJson1 TO $'''{
\"a\":null,
\"b\" : Null,
\"c\" : null ,
\"Checknull\": false,
\"name\" : \"janull nulla\",
\"null_check\":true,
\"test\": \"私はnull\",
\"test1\":\"null\",
\"test2\":\"今日は null \",
\"test3\": null
}'''
Text.Replace Text: SampleJson1 TextToFind: $'''(?<=:\\s*)null(?=\\s*|,|})''' IsRegEx: True IgnoreCase: True ReplaceWith: $'''\"\"''' ActivateEscapeSequences: False Result=> Replaced
Variables.ConvertJsonToCustomObject Json: Replaced CustomObject=> JsonAsCustomObject
Web.InvokeWebService.InvokeWebService Url: $'''https://jsonplaceholder.typicode.com/posts''' Method: Web.Method.Get Accept: $'''application/json''' ContentType: $'''application/xml''' ConnectionTimeout: 30 FollowRedirection: True ClearCookies: False FailOnErrorStatus: False EncodeRequestBody: True UserAgent: $'''Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6''' Encoding: Web.Encoding.AutoDetect AcceptUntrustedCertificates: False ResponseHeaders=> WebServiceResponseHeaders Response=> WebServiceResponse StatusCode=> StatusCode
Text.Replace Text: WebServiceResponse TextToFind: $'''(?<=:\\s*)null(?=\\s*|,|})''' IsRegEx: True IgnoreCase: True ReplaceWith: $'''\"\"''' ActivateEscapeSequences: False Result=> Replaced2
Variables.ConvertJsonToCustomObject Json: Replaced2 CustomObject=> JsonAsCustomObject2
まとめ
- Power Automate for desktopのカスタムオブジェクト型ではnull値の扱いが今のところ難しいようです。
- 暫定的ですが正規表現の肯定後読みと肯定先読みを組み合わせた置換でほとんどのパターンは処理することができました。
- しかし検索パターンに該当するnullがKEYや値に内包された場合は対応できません。( ノД`)シクシク…
- ノーコード、ローコードツールは手軽ですが、いろいろなケースでテストしたほうがよいと思います。
- Web APIから返ってくるJSONっていろいろだし💦