Power Automateでデータを取り扱ううえで欠かせないのがJSONという書式であり、そのデータの解析を行うためのアクションとしてクラウドフローでは 「JSONの解析」アクションが提供されています。
このアクションを利用するケースの多くは、単純にサービスから得られるデータを動的コンテンツに登録する、あるいは必須データが入っているかのチェックをする というものかと思います。
応用的な利用方法として、簡単なデータのチェック (バリデーション)が可能であることを以前の投稿で紹介しました。
Power Automate における JSON Schema の応用テクニック - MoreBeerMorePower
今回はさらにこのJSONの解析を使った、JSONスキーマを活用したデータのバリデーションについて記載します。
0. 利用例
まずはいくつかの例を考えていきます。
A. 依存関係のある必須入力
よくサービスを利用するときに、「ある特定のチェックボックスをONにしたらそれに応じて入力欄が出てくる」みたいなフォームがありますよね。支払い方法をクレジットカードにしたらクレカの番号を入力する、銀行引き落としにしたら口座番号を入力する のようなケースです。
このように、特定の選択肢に応じて必要なデータが変わるようなケースも、入力チェックをJSONスキーマの "dependentRequired" (依存関係のある必須) という機能で実行できます。
B. 値の範囲に応じたデータチェック
アカウント登録のような場合を考えます。もし未成年の場合 (年齢が17歳まで) には親権者の同意が得られているかをチェックさせるようなフォームもよく見かけます。(意味があるかは別として)
この場合、入力されたデータの年齢部分(あるいは生年月日)の範囲に応じて親の同意したかどうかのデータを判定する必要があります。普通クラウドフローでは条件のアクションを使い、OK/NGを判定しますが、これもJSON解析のアクションで判定することができます。(JSONスキーマの"If-Then-Else")
C. 3つ以上の選択肢に応じたチェック
先ほどと同様に支払い方法がイメージしやすいと思います。銀行振込なら口座番号、クレカならクレジットカード番号、着払いなら特に追加入力なし のような3つ以上の選択肢があるケースで、追加のデータが必要になるような場合です。
この時には If-Then-Else と allIOf を利用することで、JSONの解析の中でデータの正当性を確認できます。
では実際にどのように実装していくかを見ていきましょう。
1. 実装方法
Power Automate側では非常にシンプルに、作成アクションでチェックすべきデータを設定し、JSONの解析アクションでそのデータの正当性をチェックするという構成にします。 正当なデータならアクションが成功、不正なデータであればアクションが失敗します。
A. 依存関係のある必須入力
依存関係のある必須入力として、簡単のために「支払い方法 (paymentMethod)」が入力されていたら「カード番号 (cardNumber)」を必須とするようなケースを考えます。
つまり以下のようなパターンが許容されるようなチェックです。

"paymentMethod"があるならば"cardNumber"もあるべし とする場合、JSONのスキーマは以下のようにかけます。
{ "type": "object", "properties": { "name": { "type": "string" }, "paymentMethod": { "type": "string" }, "cardNumber": { "type": "string" } }, "required": ["name"], "dependentRequired": { "paymentMethod": ["cardNumber"] } }
ポイントは "dependentRequired" です。この中で AAAがあればBBBも入ってなさい という指定を "AAA":["BBB"] と書いています。

このような指定を1か所いれるだけで、依存関係のある必須入力をJSON解析のアクションでチェックすることができます。
ここで勘のいい読者の方は「paymentMethodがなくてnameとcardNumberだけのデータも許容されるのでは?」と思ったかもしれません。 実際、paymentMethodとcardNumberがセットで登録されているべし とする場合には、以下のようなスキーマが必要になります。
{ "type": "object", "properties": { "name": { "type": "string" }, "paymentMethod": { "type": "string" }, "cardNumber": { "type": "string" } }, "required": ["name"], "dependentRequired": { "paymentMethod": ["cardNumber"], "cardNumber":["paymentMethod"] } }
つまり共依存にすることで、入るならどっちもなくてはダメ にすることができるのです。
B. 値の範囲に応じたデータチェック
つぎに値の範囲に応じたデータチェックを考えます。利用例のところでも書いたように、年齢に応じて親権者の同意をONにしていることを求めるようなチェックです。
つまりチェック結果としては以下のようなパターンをOK/NGとしたいような場合です。

このような入力値の条件に応じた判定には "If-Then-Else" の構文を使います。(よくあるIF文をスキーマの中でも使う)
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"},
"parentalAgreement": {"type": "boolean"}
},
"required": ["name","age"],
"if": {
"properties": {
"age": {
"maximum": 17
}
}
},
"then": {
"required": ["parentalAgreement"],
"properties": {
"parentalAgreement": {
"const": true
}
}
}
}
少し複雑になりましたが、ポイントは後半部分の "if"以降です。"if"の中でやっているのは「if プロパティの"age"が最大で17の場合には、then プロパティの"parentalAgreement" は定数として trueでありなさい」という指定をしています。 それ以外の場合何らかの指定をしたければ "then"のあとに "else" を挿入します。今回は未成年なら~というだけの条件でしたので、"if"と"then”のみでチェックが完結します。

C. 3つ以上の選択肢に応じたチェック
最後に、これまでの2つを応用したパターンとして、3つ以上の選択肢がある場合の必須チェックを考えます。 支払い方法 (paymentMethod) が "card" なら "cardNumber"を必須とし、 "debit"なら"bankAccount"を、それ以外なら特になし というケースです。
この場合にはIf-Then-Else と allOf を使います。JSONスキーマのIF文にはElse IFがないので、If-Thenを複数列挙して、いずれもTrueになれ という書き方をするわけです。
{
"type": "object",
"properties": {
"name": {"type": "string"},
"paymentMethod": {"type": "string"},
"cardNumber": {"type": "string"},
"bankAccount": {"type": "string"}
},
"required": ["name","paymentMethod"],
"allOf": [
{
"if": {
"properties": {
"paymentMethod": {
"const": "card"
}
}
},
"then": {
"required": [
"cardNumber"
]
}
},
{
"if": {
"properties": {
"paymentMethod": {
"const": "debit"
}
}
},
"then": {
"required": [
"bankAccount"
]
}
}
]
}
これも抜け穴がありますね。 card 支払いで cardNumberとbankAccountのどっちも入っているケースが通ってしまいます。 その場合には dependentSchema と additionalProperties : false で解消できるでしょう。
おわりに
こんな難解なチェックはアプリ(入力側)でやればいいじゃないかと思われるかもしれませんが、フローの中でデータチェックを実施するというのは不完全な/不正なデータを登録させないという意味で非常に重要です。
フローの条件式などを使っても同様の操作・チェックはできますが、JSON解析でも結構いろいろできるよというご紹介でした。