#はじめに
UiPathを使用してAPI連携メインのロボットを作成する際、APIコールに必要な複雑なJSONを作成する方法に悩んだため、備忘用に投稿しました。
本記事はあくまでも数ある方法の中での一つでしかなく、これが正解だと言いたいわけではないことをまず申し上げておきます。
なお本記事は、@masatomix 様の下記投稿を先にご覧になったほうが理解しやすいと思います。(非常にわかりやすい記事で参考にさせていただきました)
本記事は上記の続編という扱いで見ていただければ幸いです。
#まずは結論から
とりあえず下記をおさえておけばOKです!次項から詳しく記載します。
- JSONの {変数名, 値} は、Dictionary の {TKey, TValue} で表現
- JSONの 値 を配列にしたいときは、List で表現
- Dictonary型変数 → JSON文字列への変換は
Newtonsoft.Json.JsonConvert.SerializeObject( Dictionary型変数 )
※Newtonsoft.Json.JsonConvert.SerializeObject についてはココを参照
#本記事のゴール
本記事を理解すれば、以下のようなJSONを難なく作れるようになれます!(のはず…)
{
"families": [
{
"name": "Bob",
"age": 24,
"favorite_color": [
"blue",
"green"
],
"active": true
},
{
"name": "Lisa",
"age": null,
"favorite_color": [
"red",
"purple"
],
"active": false
}
]
}
では早速いってみましょう!
#前提(開発環境とか)
####UiPath
- Studio Pro 2021.4.0-beta.158(Community License)
####使用パッケージ
Package | Version | 手動追加 |
---|---|---|
UiPath.System.Activities | 20.10.4 | |
Microsoft.Activities.Extensions | 2.0.6.9 | ※ |
UiPath.WebAPI.Activities | 1.6.0 | ※ |
※パッケージの手動追加が必要
#まずは基本のJSON作成(JSON値が文字列編)
本項は @masatomix 様の 投稿 と内容が重複しますが、基本となるため本記事でも取り上げます。
まずは以下JSONの作成方法を記載します。
{
"name": "Bob",
"email": "bob@example.com"
}
このようなシンプルな JSON であれば String 変数をゴリゴリいじって作成してもいいのですが、複雑な JSON になればなるほど実装内容がわかりづらくなる傾向があります。
そこで JSON は、以下のイメージで Dictionary を作成 → 文字列に変換、という実装をするとわかりやすくなります。
- 作成する Dictionary
Key(String) | Value(String) |
---|---|
"name" | "Bob" |
"email" | "bob@example.com" |
では Studio で実装してみます。
###Studio作成例
解説
Dim jsonDic = New Dictionary(Of String, String)
上記変数を Studio 上で定義および初期化しているので、Add to dictionary アクティビティで要素を2つ追加します。
-
2つ目の要素:Key="email", Value="bob@example.com"
これで Dictionary に要素を2つ追加することが出来ました。
※補足※
Add to dictionary アクティビティは Microsoft.Activities.Extensions パッケージをインストールしないと使えません。
「大人の事情でデフォルトのパッケージしか使えない」という方は、代入 アクティビティや、 Invoke Method アクティビティで Dictionary.Add メソッドを使うと良いでしょう。
個人的に Dictionary に要素を追加する際は、閲覧性の良さから Add to dictionary アクティビティを好んで使っています。
その後、JSON をデシリアライズ アクティビティを実行します。
このアクティビティは、JSON文字列を入力すると、それに対応するJsonオブジェクト(JObject型)の変数を返してくれます。
Json文字列 プロパティは、以下のように設定して下さい。
Newtonsoft.Json.JsonConvert.SerializeObject(jsonDic)
(上記メソッドは、引数に指定した Dictionary を JSON 文字列化して返してくれます。ただし出力されるのは整形されていない JSON 文字列です。ログで見てわかりやすくするため、今回は JSON 整形の目的のみで JSON をデシリアライズ アクティビティを実行しています)
本アクティビティの出力結果は JObject 型で返ってきます。(JObject の詳細はココを参照)
出力結果は jsonObj
変数に入っているので、この内容を ToString
で見てみます。
結果はいかに...?
想定どおりのJSON文字列を作成することができました
Dictionary を使用することで、
- Key → JSONの変数名
- Value → JSONの値
という変換が簡単にできる、というのが基本となる重要なポイントです
#JSON値が数値の場合
では欲しいJSON値が数値の場合、どうしたらいいでしょうか?
{
"age": 24
}
JSON値が数値の場合でも基本は同じで、Dictionary を作成 → 文字列に変換 という流れは変わりません。
先ほどの例との変更箇所は、Dictionary<TKey, TValue>
の TValue
の型が String → Int32 に変わるのみ です。
Key(String) | Value(Int32) |
---|---|
"age" | 24 |
では Studio で実装してみます。
###Studio作成例
解説
Dim jsonDic = New Dictionary(Of String, Int32)
上記変数をStudio上で定義および初期化しているので、Add to dictionary アクティビティで要素を1つ追加します。
想定通りのJSONが作成できました!
Dictionary の TValue の型を Int32 で定義したので、それに合わせて出力される文字列が 24 となりダブルコーテーションで括られず、JSON仕様的に正しい数値型として出力されている のがポイントです
#JSON値が真偽値の場合
欲しいJSON値が真偽値の場合でも、対応方法はまったく同じです。
{
"active": true
}
今回も同様に、欲しいJSON値の型に合わせて Dictionary<TKey, TValue>
の TValue
の型を Boolean に変えるのみ です。
Key(String) | Value(Boolean) |
---|---|
"active" | true |
ではStudioで実装してみます。
###Studio作成例
解説
Dim jsonDic = New Dictionary(Of String, Boolean)
上記変数をStudio上で定義および初期化しているので、Add to dictionary アクティビティで要素を1つ追加します。
こちらも想定通りですね!
Dictionary の TValue
の型を Boolean で定義したので、それに合わせて出力される文字列が true となりダブルコーテーションで括られず、JSON仕様的に正しい真偽値として出力されている のがポイントです
#JSON値に複数の型が必要な場合
ここからが実践編です。
以下のように、APIのパラメータに複数のJSON値の型を指定しなければならないケースがあります。
{
"name": "Bob",
"age": 24,
"active": true
}
今までは欲しいJSON値の型に合わせて Dictionary<TKey, TValue>
の TValue
の型を定義していましたが、複数の型が必要な場合は Object 型で定義 します。
Key(String) | Value(Object) |
---|---|
"name" | "Bob" |
"age" | 24 |
"active" | true |
ではStudioで実装してみます。
###Studio作成例
解説
Dim jsonDic = New Dictionary(Of String, Object)
上記変数をStudio上で定義および初期化しているので、Add to dictionary アクティビティで要素を3つ追加します。
- 1つめの要素:Key="name", Value="Bob" (String)
- 2つめの要素:Key="age", Value=24 (Int32)
- 3つめの要素:Key="active", Value=True (Boolean)
Dictionary を Object
型で定義したことで、変数値に複数の型を入力できているのがポイントです
バッチリですね!
このように 変数値に複数の型が必要な場合は、Dictionary の TValue
は Object
型で定義 すると目的のJSONを簡単に作ることが出来ます。
#JSON値が配列の場合
JSON値には仕様上、以下のように配列を指定することができます。
{
"favorite_colors": [
"red",
"green",
"blue"
]
}
冒頭で記載したとおり、配列は List<T>
で表現します。
上記のJSON値が必要な場合、Dictionary の TValue
は List<String>
型で定義すると目的のJSONを作成可能です。
Key(String) | Value( List<String> ) |
---|---|
"favorite_colors" | {"red", "green", "blue"} |
ではStudioで実装してみます。
###Studio作成例
解説
' favorite_colors の値用の List 型変数
Dim listColors = New List(Of String)
' JSON 作成用の Dictionary 型変数
Dim jsonDic = New Dictionary(Of String, List(Of String))
上記変数をStudio上で定義および初期化しています。
まずは listColors
変数に対して、"red" "green" "blue" の値を3つ追加します。
List<String>
型の変数へ値を追加する方法はいくつかありますが、今回はデフォルトで用意されている コレクションに追加(Add To Collection) アクティビティを使ってみます。
今までと同様、上記 listColors
変数を Add to dictionary アクティビティで追加します。
配列の値がブラケット([])付きで出力されました!
このように 変数値に配列が必要な場合、Dictionary の TValue
は List<T>
型で定義 すると目的のJSONを簡単に作ることが出来ます。
※補足※
「配列は List<T>
で表現する」と記載しましたが、直接配列を定義しても同じ結果を取得することができます。
今回の例で言うと、List<String>
ではなく String(2)
という String型の配列でも実現可能です。
どちらが正解というわけではありませんが、直接配列を定義すると要素数の定義等で少し実装がややこしくなるため、個人的には List<T>
で実装したほうがシンプルになるかと考えています。
#JSON値が オブジェクト型 の場合
以下のように、JSON値にはオブジェクト型も指定可能です。
{
"user_info": {
"user_id": "A1234567",
"user_name": "Bob"
}
}
若干トリッキーですが、こういったケースは Dictionary の値に、更に Dictionary を格納する ことで対応可能です。
以下のイメージで変数を定義すればOKです。
Key(String) | Value( Dictionary<String, String> ) |
---|---|
"user_info" | Dictionary<String, String>(←"user_id" と "user_name" を格納) |
若干イメージ湧きづらいかもしれませんね。
ではStudioで実装してみます。
解説
' Bob の情報を格納する Dictionary
Dim BobDic = New Dictionary(Of String, String)
' Bob 用の Dictionary 自体を値に持つ、Dictionary
' (TValue は Object の定義でも可)
Dim jsonDic = New Dictionary(Of String, Dictionary(Of String, String))
上記変数をStudio上で定義および初期化しています。
まずはDictionary変数 BobDic
に、Bob専用の情報を2つ格納します。
次にそれを包み込むような形で、Dictionary 変数 jsonDic
の値に上記 BobDic
を格納します。
完成した Dictionary 変数 jsonDic
を、JSON文字列に自動変換
想定通りのJSONが出力されました!
JSONの仕様上、オブジェクトは階層構造を持つことができます。
Dictionary の値の中に、更に Dictionary を格納することで実現可能、ということが今回の重要なポイントです
#JSON値が null
の場合
JSON値には仕様上、null を指定することもできます。
###JSON値が文字列型の場合に null
が必要なケース
{
"first_name": "Bob",
"last_name": null
}
VB.NET での null
の表現は Nothing
ですから、必要な Dictionary は以下になる、というのは想像が付くかと思います。
Key(String) | Value(String) |
---|---|
"first_name" | "Bob" |
"last_name" | Nothing |
ではStudioで実装してみます。
###Studio作成例
解説
Dim jsonDic = New Dictionary(Of String, String)
上記変数をStudio上で定義および初期化しているので、Add to dictionary アクティビティで要素を2つ追加します。
想定通りのJSONが作成できました!
Dictionary の Value 値に Nothing を代入すると、JSON文字列に変換したときに null と正しく表現されているのがポイントです
JSON値が数値型の場合に null
が必要なケース
数値型の場合は少し注意が必要です。例えば以下のケースで考えてみます。
{
"height": 173,
"weight": null
}
今までの記事を参考にして、必要な Dictionary は以下で定義してみます。
Key(String) | Value(Int32) |
---|---|
"height" | 173 |
"weight" | Nothing |
Studio での実装例は前項の String 型とほぼ同じであるため割愛しますが、注目したいのは以下の出力結果です。
なんと weight がゼロで出力 されてしまいました…これは想定外ですね。
Int32型の変数に Nothing を代入した結果は、0 という文字列で出力されてしまう
ということを抑えておく必要があります。
対策として、以下の形で Dictionary を定義すると想定通りのJSONを取得することが出来ます。
(TValue
の型を Int32
ではなく、Object
で定義する)
Key(String) | Value( |
---|---|
"height" | 173 |
"weight" | Nothing |
weight の値が null となりました、想定通りのJSONになりましたね!
###JSON値が真偽値の場合に null
が必要なケース
真偽値の場合でも、数値型と同じ問題が発生します。例えば以下のケースです。
{
"active": true,
"marriage": null
}
必要な Dictionary は以下で定義してみます。
Key(String) | Value(Boolean) |
---|---|
"active" | true |
"marriage" | Nothing |
こちらも Studio での実装例は割愛しますが、注目したいのは以下の出力結果です。
marriage が false で出力 されてしまいました…。
Boolean型の変数に Nothing を代入した結果は、false という文字列で出力されてしまう
ということも合わせて抑えておく必要があります。
対策として、以下の形で Dictionary を定義すると想定通りのJSONを取得することが出来ます。
(TValue
の型を Boolean
ではなく、Object
で定義する)
Key(String) | Value( |
---|---|
"active" | true |
"marriage" | Nothing |
marriageの値が null となりました!
###null値が必要な場合のまとめ
変数へ Nothing
代入後、JSON文字列へ変換した際に出力される文字列をまとめます。
変数の型 | JSON変換後の値 | 結果 |
---|---|---|
String | null | OK |
Int32 | 0 | NG |
Boolean | false | NG |
Object | null | OK |
以上のことから、**JSON値に null
が必要な場合、Dictionary の TValue
の型は Object
型で定義**しておくと良いでしょう。
#最終章:目的のJSONを作成してみよう
ここまでの内容を抑えておけば、冒頭で触れた目的のJSONが作成可能になるはずです。
{
"families": [
{
"name": "Bob",
"age": 24,
"favorite_color": [
"blue",
"green"
],
"active": true
},
{
"name": "Lisa",
"age": null,
"favorite_color": [
"red",
"purple"
],
"active": false
}
]
}
上記JSONを分解して必要な変数(と型)を割り当てられればOKなのですが、この複雑度だと頭の中だけで考えるのはツラくなってきますので図に起こしてみます。
左側が作成したいJSON、右側が対応する変数と型を定義した図です。
実務を想定すると「Bob用とLisa用で変数を分ける」という実装は有り得ないのですが、今回は話をシンプルにするためにあえて変数を分けています。
図を整理すると、以下の形になります。
- ①と②:Bob一人分の情報を格納する変数
- ③と④:Lisa一人分の情報を格納する変数
- ⑤Bob と Lisa をまとめる List
- ⑥全部をまとめる Dictionary
ここまで整理できれば Studio で実装が可能になります。
早速やってみます!
###Studio作成例
解説
上記ワークフローだけだと全然わかりませんね(笑)
一つずつ記載していきます。
####Bobの情報作成(変数①と②)
まずは Dictionary である dicBob
変数に以下の値を追加します。
Key(String) | Value(Object) | 備考 |
---|---|---|
"name" | "Bob" | ← |
"age" | 24 | ← |
次に List である favColorsBob
に、Bob の好きな色を追加します。
- 1つ目の要素 "blue"
- 2つ目の色 "green"
作成したList変数 favColorsBob
を、Bobの情報を格納するDictionary dicBob
に追加します。
Key(String) | Value(Object) | 備考 |
---|---|---|
"name" | "Bob" | |
"age" | 24 | |
"favorite_color" | {"blue", "green"} | ← |
最後に active=True を dicBob
に追加し、Bob 用の情報は全て格納完了となります。
Key(String) | Value(Object) | 備考 |
---|---|---|
"name" | "Bob" | |
"age" | 24 | |
"favorite_color" | {"blue", "green"} | |
"active" | True | ← |
以上で Bob 一人分の情報を格納する Dictionary 変数である dicBob
が完成しました!
####Lisa の情報作成(変数③と④)
こちらは Bob の情報作成方法とほぼ同じであるため、実装内容は割愛します。
最終的に以下の形の Dictionary 変数 dicLisa
が完成していればOKです!
Key(String) | Value(Object) |
---|---|
"name" | "Lisa" |
"age" | Nothing |
"favorite_color" | {"red", "purple"} |
"active" | False |
####Bob と Lisa をまとめる List(変数⑤)
次にList型変数 familyList
に、Bob情報(dicBob)と、Lisa情報(dicLisa)を格納します。
- 1つ目の要素
dicBob
- 2つ目の要素
dicLisa
####全部をまとめる Dictionary(変数⑥)
最後に今まで作成した変数をまとめる Dictionary型変数 jsonDic
に値を格納します。
目的のJSON文字列を作成することができましたね
#最後に
Dicationary と List の組み合わせだけで、JSONを自在に作成可能なことがわかりました!
もし他にもっとスマートなやり方等をご存じでしたら、ご指摘いただけますと幸いです。
#参考にしたサイト、記事
下記の素晴らしい記事を参考にし、UiPathで色々と検証させていただきました。
ありがとうございます