コラム 「RPAの気になる話」

UiPath StudioでJSONデータをもっと活用するために

2022.02.01

> UiPath製品に関する情報はこちら
> WinActor製品に関する情報はこちら

1. RPAとJSONの関係

今回のテーマのJSONは多くの場合、API連携の中で扱うものです。RPAでデータを取得する方法はGUI操作とAPI連携の2通りあり、APIを使うメリットは多いです。(APIには幾つか種類がありますが、当コラムのAPIWeb APIを指しています)。

そもそも、GUI(グラフィカル・ユーザー・インターフェース)とは、コンピューターへの実行命令を人間が直感的に行えるようにするための媒体です。これに対し、API(アプリケーション・プログラミング・インターフェース)とは、ウェブ上で公開されているサービスのプログラム機能を呼び出し、返ってくるデータをRPAなどの外部アプリケーションで利用できるようにする手順のようなものです。

キーボードでキー送信したり、マウスでカーソル移動してクリックしたり…といったGUI操作は、操作パターンが無数に存在する事や、操作対象システムやRPAの実行環境に依存する事から動作が不安定になりがちです。その点、機能を使うための手順が明確で、常に同じ手順でアクセスできるAPIの方がデータをより安定的に取得できるのです。このほか、開発効率性や保守性の良さも期待できます。

APIの多くで採用されているJSONの知識があると、こうしたAPI連携のメリットを活かせるようになります。ここでは、JSON形式で返されたデータをRPA側でうまく活用する方法を解説していきます。なお、当コラムはセミナー「デモで紹介!RPAとAI-OCRで紙業務をデジタル化する」の開発裏話として執筆しており、デモで使用した「Robota」がAPIの例として登場します。

 

2. APIコールからJSONデータ取得までの流れ

2.1. RPAAPIの連携イメージ

UiPath StudioからAPIRobota」のOCR機能を呼び出して利用する流れを図で示しました。このコラムでは「⑤ JSONデータ処理」の部分を詳しく説明しています。

なお、図の中の「Robota」はAI-OCR処理を行うAPIです。「Robota」には、実際には2回のHTTPリクエスト(POSTリクエスト1回、GETリクエスト1回)を行いますが、分かりやすくするため図の中では単純化しています。

  1. UiPath Studioから領収書の登録をリクエスト。RPA端末がプロキシを設定した閉域ネットワーク(例えば社内ネットワーク)にある場合、UiPath Studioの端末でプロキシを経由するよう設定しましょう。
  2. Robota」は、送信元のグローバルIPアドレスで認証(リクエストしたユーザーがAPIの利用権限をもつかどうか確認)します。認可を得られたHTTP通信について、リクエスト内容が実行されます。
  3. 1回目のリクエスト(POSTメソッド)では、「Robota」は領収書画像をAPIサーバー上に登録し、UiPath Studioに対し、登録した画像の識別IDを返します。2回目のリクエスト(GETメソッド)は識別IDを使ってOCR処理を要求します。「Robota」は指定された識別IDの画像をAI-OCR処理し、領収書の読取結果として返します。
  4. Robota」はAPIのレスポンスデータとして標準的なJSONフォーマットでデータを返します。
  5. UiPath Studioでは前処理として受け取ったJSONデータを元のJSONオブジェクトに復元し、扱いやすくするためにデータ成型を行ってからワークフローに組み込みます。

 2.2 JSONとは

JSONJavaScript Object Notation)とはプログラム間でデータを受渡しするために定義されたデータ交換方式の1つで、JavaScriptのオブジェクト記法に則しています。基本的な記法は次の通りです。

  • 「オブジェクト」は、{} 内にコロンで区切られたキー(key)と値(value)のセットで構成されています(①)
  • 複数指定する場合、コンマ(,)で区切ります(②)
  • オブジェクトは入れ子構造にすることができます。オブジェクトの値(value)に更にオブジェクト( {“key”,”value”} )をネストできます(③)
  • 配列を使用する場合、{}ではなく[]内にコンマ区切りで記述します(④) 

 

3. 「Jsonを逆シリアル化」するとは

APIから返されるJSONデータは、データを送受信するためのバイト文字列(JSON文字列)の状態です。RPA側ではまず、項番2.2で説明したオブジェクトの状態に復元し、RPA側で扱いやすいよう成型しなおす処理が必要です。

UiPath Studioでは [Jsonを逆シリアル化] アクティビティを使います。アクティビティのプロパティ設定で [Newtonsoft.Json.Linq.JObject] 型を指定し、JObject 型変数「jObj_領収書読取GET」に出力するとします。「jObj_領収書読取GET」には、以下のイメージのようにオブジェクトの状態が復元され、JSONデータをJObject 型で扱えるようになります。

キー 「result」のバリューである「SUCCESS」は

 jObj_領収書読取GET(“result”).ToString

と簡単に取り出せますが、非課税合計金額にあたるキー「tax_free_amount」のバリューの「220」は

 jObj_領収書読取GET(“data”)(“items”)(“options“)(“amount_detail“)(“tax_free_amount”).ToString

と指定する必要があり、可読性や保守性の点であまり良くありません。たとえば「tax_free_amount」とルートの途中の「amount_detail」のキー名が変更されたり、所属するオブジェクトが「amount_detail」から「data」へ変わったりするケースが考えられます。その場合、UiPath側では [null] を取得することになり、バリューを処理する段階でエラーが発生するでしょう。

当コラムでは3つのポイントを押さえて、バリューを簡単に取り出すための成型処理ワークフローを解説します。

 ① 辞書型のキーとバリューに出力する

上の逆シリアル化の例は、UiPath公式ドキュメントで紹介されている変換方式に倣っていますが、ここでは「繰り返し(コレクションの各要素)」を使って、Json文字列のキーと値を、より扱いやすい辞書型変数のキーとバリューに出力していきます。

 ② ネスト構造であるJSONデータについて、バリューがJObject型でなくなるまで逆シリアル化を繰り返す

元のオブジェクト構造を復元する目的であれば逆シリアル化は1度だけで良いと思いますが、値を掘り起こすとき、キーひとつで値を取得できるのは「現在の」階層(ここでは、逆シリアル化対象のJSONデータを元のオブジェクト構造に復元したときの最上位階層を指すことにします)になります。この特徴を利用して、逆シリアル化で出力する作業用辞書のバリューのデータ型がJObject型であれば、これを「.ToString」で文字列にし、再度逆シリアル化を繰り返します。

③再帰呼び出しする

深いネスト構造になっているJSONデータの逆シリアル化処理は大変そうに思えますが、一度基本の流れを作り「ワークフローとして抽出」し、その中で自身を呼び出す「再帰」を使えば開発の手間を省くことができます。

基本の考え方は、「Jsonを逆シリアル化」して抽出したバリューがJObject型である場合、さらにそれを逆シリアル化、抽出したバリューがさらにJObject型であれば、さらにそれを逆シリアル化・・・(以下繰り返し)・・・バリューがJObject型でなくなったらキーとバリューをセットで親辞書に登録となります。

 「Jsonを逆シリアル化」を再帰的に行うことで、処理がシンプルになる点、開発効率が向上する点のメリットを得られます。また、逆シリアル化する際にキー名のハードコーディングを避けられるので、JSONデータを扱う他のワークフローにも再利用できるようになります。

当コラムで解説するワークフローでは最終的に以下の辞書を生成します。先の例の「tax_free_amount」の取得は、

 領収書読取結果_辞書データ(“tax_free_amount”).ToString

のように、もっと簡単に書けるようになります。

 

4. JSONデータを辞書に変換する再帰処理をつくる

事前準備として、辞書型変数を扱うアクティビティを利用できるようにします。UiPath Studioのデザインタブの「パッケージを管理」から開く画面で [Microsoft.Activities.Extensions]を検索し、「インストール」→「保存」します。プロジェクトの依存関係に追加されると、アクティビティパネルから利用できるようになります。(UiPath Studioのバージョンは2021.10.4を使っています)

ここからは呼出元の【領収書読取API連携(curl)と呼出先のJson情報を辞書登録】という2つのワークフローを使って説明していきます。

4.1 呼出元 【領収書読取API連携(curl)】

Mainから呼び出される【領収書読取API連携(curl)は、領収書の画像ファイルを「Robota」に連携しレスポンスデータを受け取ります。レスポンスデータはJson情報を辞書登録】を呼び出し、最終的にひとつの親辞書にまとめます。

 

  1. POSTメソッド、GETメソッドの2回のリクエストを行い、結果をJSONオブジェクトで取得。
  2. 親辞書を最終形にもっていく作業は呼出先の【Json情報を辞書登録】で行いますが、当ワークフローでも一度だけ逆シリアル化します。これにより、【Json情報を辞書登録】では、JSONオブジェクトのルート階層のキーを取得できるようになります。次のように、[出力に格納されるデータ型を指定する[TypeArgument]には[System.Colletions.Generic.Dictionary<TKey,TValue>]を選択し、キー名を格納するTKey[String]型、JSONオブジェクトを格納するTValue[Object]型を設定します。これでルート階層のJSONオブジェクトのキーと値が、作業用の辞書型変数「一度逆シリアル化したGETメソッドの応答」のキーとバリューに出力されます。
  3. Invoke Workflow File(ワークフローファイルを呼び出し)」アクティビティで【Json情報を辞書登録】を呼び出し、JSONデータをまとめた辞書型変数を取得します。
  4. Mainのワークフローに返す引数に 3. で取得した辞書を設定します

 

ポイント解説 ― JSONデータのMainへの返し方はAPIの仕様も考慮する 

取得したJSONデータをどのようにMainに返すかは、APIの仕様でも変わってきます。

辞書変数へのアクセス制限や変数スコープを厳密に管理するといった機能面を考慮すれば【領収書読取API連携(curl)で親辞書の情報を取得し、必要な情報だけMainに返すのがセオリーですが、「Robota」はオプション機能追加により読取項目を増やすことができるAPIのため、そうしたJSONデータの変更に対応しやすいよう、データをまるごとMainに返すようにしています。

 

4.2 呼出先 【Json情報を辞書登録】

[繰り返しコレクションの各要素)] の中に以下のように処理を配置しています。

呼出元から受け取る辞書を格納した引数IO_Jsonオブジェクトを逆シリアル化した辞書」の各キー(以下 item)に対し繰り返します。[次のコレクション内の各要素]には「IO_Jsonオブジェクトを逆シリアル化した辞書.Keys」と設定しています。

  1. 当ワークフローの実行回数をカウントします
  2. 以下3の分岐グループの条件式に使用するためのBoolean型変数「処理対象外キー判定」の値を取得します。JObject型のバリューをそのまま親辞書に登録したい場合があるため、そのような「逆シリアル化しないキー」を予めリスト化しておき、itemのキー名と突き合わせて判定結果を取得します。ここがTRUEの場合、3の条件分岐グループ内で逆シリアル化しない場合の処理を実行します
  3. itemのバリューのデータ型がNewtonsoft.Json.Linq.JObject型であり、かつ上記2の「処理対象外キー判定」がFALSEの場合、バリュー(JObject型変数)を [.ToString] で文字列にした上で逆シリアル化、新たな作業用辞書として出力。再度当ワークフローを呼び出します(再帰します)。出力した辞書は再帰による実行後に繰返しコレクションとして処理するため、[ワークフロー ファイルを呼び出し]アクティビティの[呼び出されたワークフローの引数]パネルで入力引数として設定します。
    条件に合致しない場合、itemのバリューをキー名とセットで親辞書に登録します。
    この部分を展開すると次のようになります。

ポイント解説 ― 全て逆シリアル化する必要はない

以下の条件式のように、「処理対象外キー判定」で逆シリアル化しない場合の条件式を含めています。

 TypeOf In_Jsonオブジェクトを逆シリアル化した辞書.item(item) Is Newtonsoft.Json.Linq.JObject AND 処理対象外キー判定 = False

逆シリアル化をあえて行わないケースとして、処理に使う予定のない値である場合と、意味のあるまとまりでなくなる場合の2つが挙げられます。

1点目、ワークフローで使う予定のないキーは「値抽出を目的とした逆シリアル化」が不要ですので、処理の効率性を考慮してそのまま親辞書に登録します。処理速度が低下しうるという再帰処理のデメリットをカバーする上で効果的です。

2点目について、当ワークフローはあくまで元のオブジェクトから「値」を取得しやすくすることを目的としており、JValue(下の階層に「構造体を内包しない単体の値」のイメージです)や、配列(JArray)の値まで抜き出すことは本質ではありません。

「意味のあるまとまりでなくなる場合」の例として、「positions」というキーが分かりやすいです。このキーは領収書画像から読み取った項目の左右上下の位置座標を返すものですが、もし「date」の「left_top」のx, yまで分解してしまうと「日付の左上の座標」という意味が成り立ちません。

{“date”:{“left_top”:{“x”:603,”y”:549},”right_top”:{“x”: (…以下省略)}

このように、かたまりで意味を成す値は、構造体の状態が維持されるべきものとしてJObject型のまま親辞書に登録し、値の抽出は別途対応します。

ポイント解説 ― 辞書登録はトライキャッチで囲う

親辞書に登録しようとしているJSONオブジェクトのキー名が、上位階層のオブジェクトのものと重複するケースが想定されます。今回のように全階層のオブジェクトを一つの辞書に生成しなおす場合、キーの重複は許されません。「Add to dictionary」アクティビティを[トライキャッチ]アクティビティの[Try]に配置しましょう。


たとえば「confidences」のバリューに含まれる「date」、「amount」、「tel」、「logo」、「issuer_name」という5つのJSONオブジェクトがあります。このうち、「date」、「amount」、「tel」が既に親辞書に登録されているとします。この場合、例外が発生し「同一のキーを含む項目が既に追加されています。」というエラーメッセージが出力されます。

APIリファレンスでJSONオブジェクト全体にキー名の重複がないかチェックしておき、重複がある場合は先のポイント解説のように、ここでは逆シリアル化をスキップし値の抽出は別途対応した方が良さそうです。

ポイント解説 ― 再帰処理のプロパティ設定・引数の方向を再確認

[Invoke Workflow File(ワークフローファイルを呼び出し)] アクティビティで自分自身の処理を呼び出す(再帰する)時、確認したい点が2つあります。

① プロパティ[分離]にチェックが入っていないこと
これにチェックを入れると呼出先のワークフローが別プロセスとして実行されます。自身を繰り返し呼び出す再帰処理で適用すると、複数のプログラムを次々と起動するような状態に陥り、システム負荷が高まります。処理速度が低下する一因になるので、特別な理由がなければチェックしないことをおすすめします。

②再帰処理で再帰後に引き継ぎたい値は、引数の方向を[入力/出力]にする
再帰処理を繰り返しながら追加更新するデータは、入力であると同時に、再帰後のプロセスに引き継ぐ「出力値」でもあります。このようなデータの引数方向を[入力]にすると、再帰のたびにデータが規定値にリセットされてしまい、意図しない動作につながります。

たとえば、次の辞書型変数「IO_親辞書」は、初期化する場所よって2パターンの意図しない動作が考えられます。当ワークフローとは別のワークフロー(呼出元)で初期化している場合、nullが格納されるため、1回目の再帰実行でエラーが発生します。一方、当ワークフローの規定値で初期化している場合、再帰するたびにデータがクリアされてしまい、最後の再帰実行で得られた結果だけが親辞書に格納されます(ここではエラーが生じないので、引数方向の誤りに気づきにくいでしょう)。

意図しない動作を防ぐために、引数の方向は注意したい点です。

 

5. さらに深く学びたい方へ

このコラムでは、APIから取得したJSONデータをRPAで簡単に扱えるようにするため、ネスト構造のJSONオブジェクトを再帰的に逆シリアル化して、データを一つの辞書にまとめるという方法を説明しました。API連携についてもっと知りたい方は、当コラムを題材にしたオンラインセミナーがありますのでご活用ください。お昼休みにお気軽にご視聴いただけて、Q&Aセッションでは疑問点にもお答えします。

オンラインセミナー APIを使うなら必須!RPAでJSONを使いこなす

また、本コラムではファーストアカウンティング社のAI-OCRRobota」を例に取り上げました。「Robota」がAI-OCRであることや基本機能は伝わったかと思いますが、この他のオプション機能について気になる方、AI-OCRの選定・導入や、AI-OCRとRPAの具体的な連携についてご検討されている方は、CACまでお気軽にご相談ください。

 

このコラムの執筆者

株式会社シーエーシー
アドバンスドテクノロジー本部
今泉 由莉花

世の中の自動化浸透にITの分野から携わりたいと思い2020年に入社。「お客様に最適なロボットを提供できる開発者」を目指し、技術検証などを通して複数のRPA開発ツールに触れてきました。文系出身エンジニアとして、初心者視点でWinActor・UiPath開発の躓きやすいポイント、コツや注意点をお伝えできればと思います。

RPA技術レポート無料ダウンロード

RPAで全社的な業務改善をするならCoE導入という選択肢
RPAで全社的な業務改善をするならCoE導入という選択肢
ダウンロード ダウンロード
RPAの始め方 Automation Hubで候補業務を見つけよう
RPAの始め方 Automation Hubで候補業務を見つけよう
ダウンロード ダウンロード
美しいコードをみると感動する、美しいワークフローの作り方
美しいコードをみると感動する、美しいワークフローの作り方
ダウンロード ダウンロード

RPA製品紹介