以下の内容はhttps://mofumofupower.hatenablog.com/entry/advanced_json_schemaより取得しました。


JSONの解析アクションの発展的利用方法

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解析でも結構いろいろできるよというご紹介でした。




以上の内容はhttps://mofumofupower.hatenablog.com/entry/advanced_json_schemaより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14