はじめに
Azure Logic Apps でワークフローを実装していると、「なぜか動かない」「式が正しいはずなのに結果がおかしい」という場面に遭遇することがあります。
本記事では、実装中にハマりやすい以下の2つのポイントを取り上げます。
- ① 特殊文字のエスケープ
- ②
trueの種類と使い分け
① 特殊文字のエスケープ
背景:どんなエラーが起きるのか
Teams の Adaptive Cards は JSON 形式でカードの構造を定義します。そのため、テキストに " や \ などの JSON として不正な文字が含まれていると、カードの送信時にエラーが発生します。
今回は admin"@test.com というメールアドレスを Adaptive Card の text フィールドに渡そうとした例を取り上げます。

単純なメールアドレスであれば問題なく送信できますが、" が含まれ何も処理せずAdaptive Card の text にそのまま渡すと以下のようにエラーになります。
エラーメッセージ:
{
"error": {
"code": "InvalidBotRequestMessageBody",
"message": "指定された Teams フローボット メッセージの本文に無効な JSON が使用されています。"
}
}
代表的な特殊文字と問題
| 文字 | 問題 |
|---|---|
" (ダブルクォート) |
JSON の文字列を途中で閉じてしまい、構造が壊れる |
\ (バックスラッシュ) |
JSON の制御文字として解釈され、後続の文字が誤って処理される |
回避方法 1:replace() でエスケープする
replace() 関数を使って、特殊文字を送信前に安全な形へ変換します。
replace(replace(outputs('Compose_'), '\', '\\'), '"', '\"')
📌 処理順序が重要
バックスラッシュ(\)のエスケープを必ず最初に行ってください。後から処理すると、他のエスケープで追加した \ まで二重エスケープされてしまいます。
さらにHTMLの改行タグをAdaptive Cardに有効化したい場合、replace() をネストする(複数の特殊文字を一度に処理):
replace(
replace(
replace(outputs('Compose_'), '\', '\\'),
'"', '\"'
),
'<br>', '\n'
)
保存時に「\\」が「\」に自動変換される問題
Logic Apps の式エディタには、保存ボタンを押すと \\ が自動的に \ に変換されるという挙動があります。これにより、保存前に正しく書いていた式が保存後に壊れてしまうことがあります。
回避策: 保存前に \\ を \\\\ と入力しておきます。保存後に \\ へ変換されるため、実行時には正しく \ のエスケープとして機能します。
// 保存前に入力する
replace(outputs('Compose_'), '\', '\\\\')
// 保存ボタンを押すと自動変換される(これが実行時の正しい式)
replace(outputs('Compose_'), '\', '\\')
回避方法 2:Parse JSON アクションを使う(推奨)
replace() による文字列操作は複雑になりがちです。より堅牢な方法として、Parse JSON アクションを使ってデータをプロパティ化し、Adaptive Card からそのプロパティを参照する方法があります。
Parse JSON のスキーマで "type": "string" と宣言することで、" や \ などの特殊文字が含まれていても、Logic Apps が安全に処理してくれます。
replace() を使った文字列操作が不要になり、式がシンプルになります。またスキーマで型を明示するため、データ構造の変更にも気づきやすくなります。
回避方法の比較
| 方法 | メリット | デメリット |
|---|---|---|
replace() |
アクション追加不要。細かい制御が可能 | 特殊文字の種類が増えると式が複雑。保存時の自動変換に注意が必要 |
| Parse JSON(推奨) | 式がシンプル。型安全。特殊文字を意識しなくてよい | アクションが1つ増える |
② true の種類と使い分け
なぜハマるのか
Logic Apps の Condition(条件分岐)で equals を使って true と比較する場面は頻繁にあります。ところが、true の書き方には複数の種類があり、型が合わないと常に False ルートへ進んでしまうという問題が起きます。
3種類の true
| 表記(デザイナー上) | 型 | Code view での表現 |
|---|---|---|
true(直接入力) |
Boolean | true |
"true"(直接入力) |
String | "true" |
true(式エディタで true と入力) |
Boolean式 | "@true" |
それぞれのデザイナー画面での見た目と Code view を確認します。
① Boolean の true(デザイナー直接入力)
Condition の右辺の値欄に true とそのまま入力した場合です。
Code view:
"equals": [
"@body('HTTP')?['isActive']",
true
]
② String の "true"(デザイナー直接入力)
右辺の値欄に "true"(ダブルクォート付き)とそのまま入力した場合です。
※ただし、Logic appsを保存し、再度開くと①の外見と同様となる(Code viewに違いを見えます)。
Code view:
"equals": [
"@body('HTTP')?['isActive']",
"true"
]
もう1つの方法は、式エディターで
string('true')と入力
Code view:"equals": [ "@body('HTTP')?['isActive']", "@string('true')" ]
③ 式の @true(式エディタで true と入力)
式エディタで true(クォートなし)と入力した場合です。Code view 上では "@true" として保存されます。

Code view:
"equals": [
"@body('HTTP')?['isActive']",
"@true"
]
典型的なハマりパターン
SharePoint や HTTP アクションは Boolean ではなく文字列 "true" を返すことがよくあります。

// ダブルクォートあり → 文字列型
{ "isActive": "true" }
// ダブルクォートなし → Boolean型
{ "isActive": true }
比較対象の型を間違えると、どちらの比較も常に False になってしまいます。
// ❌ 失敗:Boolean true に対して String "true" を比較 → 常に False
equals(body('HTTP')?['isActive'], "true")
// ❌ 失敗:String "true" に対して Boolean true を比較 → 常に False
equals(body('HTTP')?['isActive'], true)
さらに、String 型で比較する場合は大文字・小文字の不一致にも注意が必要です。比較元が "True"(T が大文字)で比較先が "true" だと、これも False になります。
// ❌ 大文字小文字の不一致でも False になる
equals(body('HTTP')?['isActive'], "true")
// → 比較元が "True" の場合は不一致
型が不明なときの最強パターン
比較対象が String 型か Boolean 型かわからないとき、以下の2つの方法が確実です。
方法 1:bool(...) で Boolean に統一して比較 (推奨)
bool() は String・Boolean どちらの入力も受け付け、Boolean に変換します。"true"・"True"・true いずれも Boolean の true に統一できます。
bool(body('HTTP')?['isActive'])
推奨理由: 比較相手が Boolean の true になるため、型の意図が明確でコードが読みやすいです。また bool() は "false" / false も正しく false に変換するため、true/false 両方を扱うフローでも安全に使えます。
方法 2:toLower(string(...)) で小文字統一して String 比較
string() で文字列化してから toLower() で小文字に統一します。"True"・"TRUE"・true いずれも "true" に統一できます。
注意: "yes" / "no" や "on" / "off" など、true/false 以外の文字列バリエーションを大文字小文字を無視して比較したい場合に有効です。ただし比較相手を "true" という文字列で固定するため、後から読んだときに型の意図が伝わりにくい面があります。Boolean の true/false を比較する用途では方法1を優先してください。
toLower(string(body('HTTP')?['isActive']))
| 比較対象の値 | 方法1:bool(...) + true(推奨) |
方法2:toLower(string(...)) + "true"
|
|---|---|---|
true(Boolean) |
✅ True | ✅ True |
"true"(String) |
✅ True | ✅ True |
"True"(String・T大文字) |
✅ True | ✅ True |
"TRUE"(String・全大文字) |
✅ True | ✅ True |
false(Boolean) |
✅ False | ✅ False |
デバッグ方法:実行履歴の「未加工出力の表示」で型を確認する
比較式を書く前に、実行履歴から各アクションの「未加工出力の表示」で実際の値と型を確認しておくのが確実です。
まとめ
| Tips | ポイント |
|---|---|
| ① 特殊文字のエスケープ |
replace() でネスト処理。保存時の \\→\ 自動変換に注意。Parse JSON を使うとよりシンプル |
② true の種類 |
型・大文字小文字を揃えることが重要。型が不明なときは bool(...) か toLower(string(...)) が確実。 |
Logic Apps の式エンジンは独自の挙動が多く、慣れるまでは原因の特定に時間がかかることもあります。実行履歴の「未加工出力の表示」を積極的に活用し、型や値を実際に確認しながら開発するのが一番の近道です。










