n8n-expression-syntax について
n8n ワークフロー作成者向けの式構文ガイドです。データ参照や変換、よくある誤りに加え、式、Edit Fields、Code ノードの使い分けを説明します。
主な機能
- 01式の構文と変数参照
- 02現在および他ノードのデータ参照
- 03Webhook、配列、オブジェクトの処理
- 04変換方法の選び方
- 05検証ルールとよくある誤り
活用シーン
- 01フィールドへの動的データの挿入
- 02日付、文字列、配列の整形
- 03Webhook のデータパスの誤り修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ czlonkowski/ n8n-mcp --skill n8n-expression-syntaxインストール後、Claude Code で/n8n-expression-syntaxを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
COMMON_MISTAKES.mdEXAMPLES.mdREADME.md詳細
n8n Expression Syntax
ワークフローで正しい n8n 式を書くためのエキスパートガイドです。
式の形式
n8n のすべての動的コンテンツでは、二重波括弧を使用します。
{{expression}}
例:
✅ {{$json.email}}
✅ {{$json.body.name}}
✅ {{$node["HTTP Request"].json.data}}
❌ $json.email (no braces - treated as literal text)
❌ {$json.email} (single braces - invalid)
基本変数
$json - 現在のノードの出力
現在のノードのデータにアクセスします。
{{$json.fieldName}}
{{$json['field with spaces']}}
{{$json.nested.property}}
{{$json.items[0].name}}
$node - 他のノードを参照
前の任意のノードのデータにアクセスします。
{{$node["Node Name"].json.fieldName}}
{{$node["HTTP Request"].json.data}}
{{$node["Webhook"].json.body.email}}
重要:
- ノード名は必ず引用符で囲んでください
- ノード名では大文字と小文字が区別されます
- ワークフロー内のノード名と完全に一致させる必要があります
$now - 現在のタイムスタンプ
現在の日付/時刻にアクセスします。
{{$now}}
{{$now.toFormat('yyyy-MM-dd')}}
{{$now.toFormat('HH:mm:ss')}}
{{$now.plus({days: 7})}}
$env - 環境変数
環境変数にアクセスします。
{{$env.API_KEY}}
{{$env.DATABASE_URL}}
警告:一部の n8n インスタンスでは N8N_BLOCK_ENV_ACCESS_IN_NODE が有効になっており、$env へのアクセスが完全にブロックされます。$env がエラーを返す場合は、次の代替方法を使用してください。
- 代わりに値を認証情報に保存する
- 値を手動で入力した Set ノードを使用する
- Webhook のクエリパラメーター経由で値を渡す
🚨 重大:Webhook データ構造
最もよくある間違い:Webhook データはルートにはありません!
Webhook ノードの出力構造
{
"headers": {...},
"params": {...},
"query": {...},
"body": { // ⚠️ USER DATA IS HERE!
"name": "John",
"email": "[email protected]",
"message": "Hello"
}
}
Webhook データへの正しいアクセス方法
❌ WRONG: {{$json.name}}
❌ WRONG: {{$json.email}}
✅ CORRECT: {{$json.body.name}}
✅ CORRECT: {{$json.body.email}}
✅ CORRECT: {{$json.body.message}}
理由:Webhook ノードは、ヘッダー、パラメーター、クエリパラメーターを保持するため、受信データを .body プロパティの下に格納します。
よく使われるパターン
ネストされたフィールドにアクセスする
// Simple nesting
{{$json.user.email}}
// Array access
{{$json.data[0].name}}
{{$json.items[0].id}}
// Bracket notation for spaces
{{$json['field name']}}
{{$json['user data']['first name']}}
他のノードを参照する
// Node without spaces
{{$node["Set"].json.value}}
// Node with spaces (common!)
{{$node["HTTP Request"].json.data}}
{{$node["Respond to Webhook"].json.message}}
// Webhook node
{{$node["Webhook"].json.body.email}}
変数を組み合わせる
// Concatenation (automatic)
Hello {{$json.body.name}}!
// In URLs
https://api.example.com/users/{{$json.body.user_id}}
// In object properties
{
"name": "={{$json.body.name}}",
"email": "={{$json.body.email}}"
}
式を使用しない場合
❌ Code ノード
Code ノードでは式ではなく、JavaScript で直接アクセスします!
// ❌ WRONG in Code node
const email = '={{$json.email}}';
const name = '{{$json.body.name}}';
// ✅ CORRECT in Code node
const email = $json.email;
const name = $json.body.name;
// Or using Code node API
const email = $input.item.json.email;
const allItems = $input.all();
❌ Webhook パス
// ❌ WRONG
path: "{{$json.user_id}}/webhook"
// ✅ CORRECT
path: "user-webhook" // Static paths only
❌ 認証情報フィールド
// ❌ WRONG
apiKey: "={{$env.API_KEY}}"
// ✅ CORRECT
Use n8n credential system, not expressions
変換のゲートキーパー
データを変換するノードを追加する前、またはコードを書く前に、この順序に従って、最初に当てはまる方法で止めてください。
-
使用するフィールド内の式(
{{ ... }})。プロパティへのアクセス、メソッドチェーン(.map().filter().join())、三項演算子、文字列の組み立て、Luxon による日付計算など、中間変数を使わずに「A を受け取り、B を生成する」処理は式で行います。これは、単にデータを変換するほとんどのケースに対応できます。 -
Edit Fields フィールド内のアロー関数 IIFE。中間変数、分岐、コメントが必要でも、単一のアイテムを処理する場合は、フィールド値の中で即時実行関数を使用します。
={{ (() => { const items = $json.line_items; const subtotal = items.reduce((sum, it) => sum + it.price * it.qty, 0); const tax = subtotal * 0.08; return (subtotal + tax).toFixed(2); })() }}外側の
(...)で関数を囲み、末尾の()で実行します。どちらか一方を省略すると、n8n は実行を拒否します。内部では式と同じスコープ($json、$('Node')、$now、Luxon)に加え、const/let、if/switch、try/catch、正規表現を使用できます。requireとawaitは使用できません。 -
Code ノード — 最終手段です。 データセット全体にわたる複数アイテムの集計(
$input.all())、許可リストに登録されたライブラリ、または非同期処理が必要な場合に限り使用します。
この順序が重要な理由。 これはスタイルの問題ではなく、可読性とパフォーマンスの問題です。Code ノードはサンドボックス化された VM 内で実行され、呼び出しごとのセットアップと値のマーシャリングが発生します。ロジックの実行前に 500~1000ms に達することもあるコールドスタートのコストです。(ウォーム状態でアイテム数の多い実行では、このコストは分散されます。そのため、普遍的な定数ではなく、一般的なケースでのコストとして捉えてください。)同じロジックを式または Edit Fields IIFE で実行すれば、プロセス内で数ミリ秒以内に処理でき、サンドボックスも完全に回避できます。単一アイテムの整形だけであれば、機能上の違いがないまま大きな差が生まれます。また、リクエストごとの Webhook など、頻繁に実行される処理では差が積み重なります。さらに式は、それを使用するフィールド内に表示されるため、内容を理解するために上流のノードを開く必要がありません。入力やスコープの要件が本当にある場合に限り、次の段階に進んでください。
Set ノードのアンチパターンと分岐の合流
1 つのコンシューマーにデータを渡す Set ノードを削除する
値を取り出して、下流の1 つのノードに渡すことだけを目的とする Set/Edit Fields ノードは、余計なものです。代わりに、コンシューマー側でその式を直接使います。
❌ Webhook → Set { customer_id: {{ $json.body.customer_id }} } → Postgres: WHERE id = {{ $json.customer_id }}
✅ Webhook → Postgres: WHERE id = {{ $('Webhook').item.json.body.customer_id }}
Set ノードは処理を 1 段階増やし、キャンバスを散らかし、リファクタリング時のリスクを高めますが、コンシューマー自身でできないことは何もしていません。n8n_update_partial_workflow で安全に削除するには、接続を付け替え(Set のソースとターゲット間の接続を removeConnection で削除し、ソースからコンシューマーへ直接 addConnection で接続)、コンシューマーの式を patchNodeField で元のソースノード名を参照するように変更してから、Set を removeNode で削除します。
簡単な確認方法: Set が生成する各フィールドを参照している下流ノードの数を数えます。
- 0 または 1 → 削除し、コンシューマー側で直接使います。
- 2 以上 → 残す価値があるかもしれません。
正当な例外 — 次の場合は Set を残します。
- 2 つ以上のコンシューマーが同じ派生値を使い、その派生処理が単純ではない場合(名前を付けることで読みやすくなり、一度だけ計算できます)。
- サブワークフローの最後の Return ノードとして、出力の契約を整える場合。この場合、「単一のコンシューマー」とはすべての呼び出し元を指します。そのため Set は API の境界となり、
Include Other Fields: falseにすることで出力の形をホワイトリスト化し、内部の一時フィールドが漏れないようにできます。 - フィールドの名前を変更したり、ホワイトリスト化したりするとき、それをコンシューマーの式全体に分散させず、1 か所で明示したい場合。
分岐の合流:NoOp で基準点を作る
分岐(IF/Switch/Merge の後)が合流すると、$json は「最後に実行された分岐がどれか」に依存します。これは非決定的で、誤ったデータが流れる原因に気づきにくいという問題があります。合流点に NoOp ノードを挿入し、わかりやすい名前(Combine Inputs など)を付けて、下流ノードから名前で参照します。
Branch A ──┐
├─→ [NoOp: Combine Inputs] ──→ downstream uses $('Combine Inputs').item.json.x
Branch B ──┘
NoOp はリファクタリング後も参照先として残ります。たとえば後から NoOp とコンシューマーの間に変換ノードを挿入しても、$('Combine Inputs') の参照は壊れません。(分岐ごとに異なるデータ形状が生成される場合は、NoOp の代わりに Set ノードを使い、両方を同じ形状に正規化します。上記の例外を参照してください。)
より広く言えば、分岐の多いフローでは、深い $json.x よりも $('Node').item.json.x を優先してください。 中間ノードを挿入したり、ノードがアイテムコンテキストをクリアしたりすると(Aggregate、Run for All を使う Code、分岐の合流など)、$json は機能しなくなります。その場合、エラーが出ないまま下流に誤ったデータが渡されます。ノード名による参照なら、ソースとコンシューマーの間に何があっても、参照先が曖昧になりません。
検証ルール
1. 常に {{}}
式は必ず二重中括弧で囲みます。
❌ $json.field
✅ {{$json.field}}
2. スペースや特殊文字には引用符を使う
スペース、発音区別符号、特殊文字を含むフィールド名やノード名には、ブラケット記法が必要です。
❌ {{$json.field name}}
✅ {{$json['field name']}}
❌ {{$node.HTTP Request.json}}
✅ {{$node["HTTP Request"].json}}
// Bracket notation is mandatory for keys with special characters
✅ {{$json['Gross Price w/o shipment']}}
✅ {{$json['Cena brutto zł']}}
3. ノード名を正確に一致させる
ノード参照では大文字と小文字が区別されます。
❌ {{$node["http request"].json}} // lowercase
❌ {{$node["Http Request"].json}} // wrong case
✅ {{$node["HTTP Request"].json}} // exact match
4. {{}} を入れ子にしない
式を二重に囲まないでください。
❌ {{{$json.field}}}
✅ {{$json.field}}
よくある間違い
エラーと修正方法の一覧は、COMMON_MISTAKES.md を参照してください。
簡単な修正方法
| 間違い | 修正方法 |
|---|---|
$json.field | {{$json.field}} |
{{$json.field name}} | {{$json['field name']}} |
{{$node.HTTP Request}} | {{$node["HTTP Request"]}} |
{{{$json.field}}} | {{$json.field}} |
{{$json.name}}(Webhook) | {{$json.body.name}} |
'={{$json.email}}'(Code ノード) | $json.email |
使用例
実際のワークフロー例は、EXAMPLES.md を参照してください。
例 1:Webhook から Slack へ
Webhook の受信内容:
{
"body": {
"name": "John Doe",
"email": "[email protected]",
"message": "Hello!"
}
}
Slack ノードのテキストフィールド:
New form submission!
Name: {{$json.body.name}}
Email: {{$json.body.email}}
Message: {{$json.body.message}}
例 2:HTTP Request からメールへ
HTTP Request の戻り値:
{
"data": {
"items": [
{"name": "Product 1", "price": 29.99}
]
}
}
Email ノード内(HTTP Request を参照):
Product: {{$node["HTTP Request"].json.data.items[0].name}}
Price: ${{$node["HTTP Request"].json.data.items[0].price}}
例 3:タイムスタンプの書式設定
// Current date
{{$now.toFormat('yyyy-MM-dd')}}
// Result: 2025-10-20
// Time
{{$now.toFormat('HH:mm:ss')}}
// Result: 14:30:45
// Full datetime
{{$now.toFormat('yyyy-MM-dd HH:mm')}}
// Result: 2025-10-20 14:30
データ型の処理
配列
// First item
{{$json.users[0].email}}
// Array length
{{$json.users.length}}
// Last item
{{$json.users[$json.users.length - 1].name}}
オブジェクト
// Dot notation (no spaces)
{{$json.user.email}}
// Bracket notation (with spaces or dynamic)
{{$json['user data'].email}}
文字列
// Concatenation (automatic)
Hello {{$json.name}}!
// String methods
{{$json.email.toLowerCase()}}
{{$json.name.toUpperCase()}}
数値
// Direct use
{{$json.price}}
// Math operations
{{$json.price * 1.1}} // Add 10%
{{$json.quantity + 5}}
高度なパターン
条件付きコンテンツ
// Ternary operator
{{$json.status === 'active' ? 'Active User' : 'Inactive User'}}
// Default values
{{$json.email || '[email protected]'}}
日付の操作
// Add days
{{$now.plus({days: 7}).toFormat('yyyy-MM-dd')}}
// Subtract hours
{{$now.minus({hours: 24}).toISO()}}
// Set specific date
{{DateTime.fromISO('2025-12-25').toFormat('MMMM dd, yyyy')}}
文字列の操作
// Substring
{{$json.email.substring(0, 5)}}
// Replace
{{$json.message.replace('old', 'new')}}
// Split and join
{{$json.tags.split(',').join(', ')}}
パフォーマンス:式の複雑さは(ほぼ)コストになりません
複雑な {{ }} は遅いのではないか、と心配されることがあります。しかし、そうではありません。コストがかかるのは式の複雑さではなく、n8n が式を評価する「回数」です。
n8n 2.x のインスタンスで測定したところ、複雑な式(sqrt、split、reduce、算術演算)のアイテムごとのコストは、単純な {{ $json.x > 50 }} と同じでした。どちらも約 ~0.2 ms/item です。これは、その約90%が式の実行ではなく、n8n がアイテムごとの評価コンテキストを構築する処理にかかるためです。
実際には、次のことを意味します。
- 「速度向上」のために、動作している式を複数のノードに分割しないでください。 ノードを追加するたびにアイテムごとに再評価が行われ、すべてのアイテムが再コピーされます。1つのノードで複雑な式を使うほうが、単純な式を使う3つのノードより高速です。
- 同じアイテムごとのチェックを行う場合、式(~0.2 ms/item)は「Run Once for Each Item」モードの Code ノード(~0.6 ms/item)より約3倍低コストです。ただし、「Run Once for All Items」モードの Code ノードなら、アイテムごとの境界を N 回ではなく1回だけ越えるため、さらに低コスト(~0.02 ms/item)です。
- これは数千件のアイテムでのみ影響します。それより少なければ100 ms未満です。アイテムごとの境界モデルの詳細は n8n Code JavaScript スキルを参照してください。
式のデバッグ
式エディターでテストする
- 式を含むフィールドをクリックします
- 式エディターを開きます(「fx」アイコンをクリック)
- 結果のライブプレビューを確認します
- 赤く強調表示されたエラーを確認します
よくあるエラーメッセージ
「Cannot read property 'X' of undefined」 → 親オブジェクトが存在しません → データパスを確認してください
「X is not a function」 → 関数ではないもののメソッドを呼び出そうとしています → 変数の型を確認してください
式がそのままテキストとして表示される → {{ }} がありません → 中括弧を追加してください
式のヘルパー
使用可能なメソッド
文字列:
.toLowerCase()、.toUpperCase().trim()、.replace()、.substring().split()、.includes()
配列:
.length、.map()、.filter().find()、.join()、.slice()
日時(Luxon):
.toFormat()、.toISO()、.toLocal().plus()、.minus()、.set()
数値:
.toFixed()、.toString()- 数学演算:
+、-、*、/、%
ベストプラクティス
✅ すること
- 動的コンテンツには必ず {{ }} を使います
- スペースを含むフィールド名にはブラケット記法を使います
- webhook データは
.bodyから参照します - 他のノードのデータには $node を使います
- 式エディターで式をテストします
❌ しないこと
- Code ノードで式を使わないでください
- スペースを含むノード名を引用符で囲み忘れないでください
- 余分な {{ }} で二重に囲まないでください
- webhook データがルートにあると思い込まないでください(.body の下にあります!)
- webhook のパスや認証情報で式を使わないでください
関連スキル
- n8n MCP Tools Expert:MCP ツールを使って式を検証する方法を学びます
- n8n Workflow Patterns:実際のワークフロー例で式の使い方を確認します
- n8n Node Configuration:式が必要になる場面を理解します
まとめ
基本ルール:
- 式は {{ }} で囲みます
- webhook データは
.bodyの下にあります - Code ノードでは {{ }} を使いません
- スペースを含むノード名は引用符で囲みます
- ノード名では大文字と小文字が区別されます
よくある間違い:
- {{ }} がない → 中括弧を追加します
- webhook で
{{$json.name}}を使う →{{$json.body.name}}を使います - Code で
{{$json.email}}を使う →$json.emailを使います {{$node.HTTP Request}}を使う →{{$node["HTTP Request"]}}を使います
詳しくは、次を参照してください:
- COMMON_MISTAKES.md - エラーの完全な一覧
- EXAMPLES.md - 実際のワークフロー例
お困りですか? n8n の式に関するドキュメントを参照するか、n8n-mcp の検証ツールを使って式を確認してください。