Set / Edit Fields:資料整形不寫程式
上一個節點吐一大包 JSON,可是下一個節點只需要其中幾個欄位、或者要合併、要改名、要加預設值——這種「換一下形狀」的事,不用寫程式。Set 節點(新版介面叫 Edit Fields)就是專門做這件事的視覺化工具。這章把它玩透,你的 workflow 會少寫一大堆 Code。
為什麼需要「資料整形」這一步
你在 第 9 章學過 items 是 n8n 的基本流動單位,每個 item 都是一包 JSON。在 第 11 章串 SaaS 節點時,你八成已經碰到這個場景:
- HTTP Request 節點吐回來:
{ firstName: "小明", lastName: "王", email: "[email protected]", age: 28, avatar_url: "...", ... } - 可是下一個 Google Sheets 節點只要三個欄位:
{ 姓名: "王小明", 信箱: "[email protected]", 年齡: 28 }
你不會想在 Sheets 節點裡寫十行 expression 硬拼,也不想動不動就開 Code 節點寫 JavaScript。你要的是一個「中間站」,把上游的 JSON 洗成下游想要的樣子——這就是 Set 節點。它不打 API、不觸發、不對外做任何事,純粹就是「把 JSON 換一個形狀」再吐出去。
Set 節點到底在做什麼
把 Set 節點想成一台加工機。它的流程就三步:
-
讀 input items
它會拿到上一個節點吐出來的所有 items(一包或多包 JSON)。跟其他節點一樣,n8n 會自動幫你對每一筆 item 執行一次。
-
依照你的設定重新組裝 JSON
你在 Set 節點裡設「要留哪些欄位、要加哪些欄位、要改哪些欄位」,它照你的規則重新組出新的 JSON。
-
吐 output items
整形好的 items 送給下一個節點。原本的 input 不受影響——Set 節點是「產出新版本」,不是「就地改 input」。
就這樣。沒 API call、沒 webhook、沒 side effect。它是 n8n 裡最快、最安全的節點之一,執行時間通常在毫秒等級。
兩個工作模式:Manual Mapping vs JSON
Set 節點打開後,最上面有個 Mode 下拉,只有兩個選項:
| 模式 | 怎麼設 | 什麼時候用 |
|---|---|---|
| Manual Mapping(預設) | 一欄一欄按 Add Field 加:Name(新欄位叫什麼)+ Type(String / Number / Boolean / Array / Object)+ Value(用 expression 或固定值) | 90% 的情況。加幾個欄位、改幾個欄位名、給幾個預設值——手動介面看得最清楚 |
| JSON | 直接貼一整段 JSON template,裡面用 {{ }} 插 expression 動態填值 |
要重新規劃 JSON 結構(例:把扁平資料變成巢狀)、或者你已經有一段 JSON 範本要照抄 |
兩個模式做的事情本質是一樣的——「產出一段新的 JSON」。差別只在你用視覺化介面設,還是自己貼 JSON 文字。新手一律從 Manual Mapping 開始,遇到需要巢狀結構時才切 JSON。
動手做:把 firstName + lastName 合成 full_name
這是最典型的 Set 節點用途。假設上游節點吐出:
{
"firstName": "小明",
"lastName": "王",
"email": "[email protected]",
"age": 28
}
你想在後面多一個欄位叫 full_name,值是 王小明(台灣人姓在前)。跟著做:
-
加一個 Edit Fields 節點
在畫布上按 + 加節點,搜
edit fields或set,選 Edit Fields (Set)。把它接在會吐出上面那包 JSON 的節點後面。 -
Mode 保持 Manual Mapping
預設就是 Manual Mapping,不用動。
-
Fields to Set 按 Add Field
下方會出現一組空白的欄位設定卡。Type 選 String(因為 full_name 是字串)。
-
Name 填
full_name這是新欄位的名字,會出現在下游看到的 JSON 裡。
-
Value 填 expression
{{ $json.lastName }}{{ $json.firstName }}Value 欄位右上角有個 Expression 切換鈕,切到 Expression 模式後貼上這串。Expression 語法看 第 14 章——
$json就是「當前這一筆 item 的 JSON」。 -
Include Other Input Fields 打勾
節點下面有一個很重要的 toggle:Include Other Input Fields(v1 UI 實際字樣,官方 docs 頁還寫舊字 Keep Only Set Fields,邏輯是反的)。打勾=保留原本的所有欄位、再加上你設的 full_name。不打勾=只留你設的欄位(其他丟掉)。這裡打勾。
-
Execute Node 看結果
按節點右上的 Execute Node。Output 面板應該吐出:
{ firstName: "小明", lastName: "王", email: "...", age: 28, full_name: "王小明" }——原本的欄位全在,多了一個 full_name。任務達成。
{{ $json.xxx }}。五種最常見的 Set 用法速查
把這五招學會,Set 節點的日常應用九成都涵蓋了。
| 要做什麼 | 設定方式 | Value 範例 |
|---|---|---|
| 加一個新欄位(時間戳、狀態標記) | Add Field,Name 填新欄位名,Value 用 expression 產值 | {{ $now }} 產當前時間;已處理 純字串 |
| 改欄位名(rename) | Add Field 新名字、Value 用 {{ $json.舊欄位 }} 引舊值;再把 Include Other Input Fields 關掉 或明列所有要留的欄位 |
Name = customer_email, Value = {{ $json.email }} |
| 給預設值(欄位缺就填) | Value 用三元運算子判斷有沒有值 | {{ $json.phone || '未提供' }} |
| 型別轉換(字串轉數字之類) | 用 JavaScript 內建函式包一下 | {{ Number($json.amount) }}、{{ String($json.id) }}、{{ Boolean($json.is_vip) }} |
| 條件填值(依上游值決定填什麼) | 用三元運算子(條件 ? A : B) |
{{ $json.amount > 1000 ? 'VIP' : '一般' }} |
這五招都是 Manual Mapping 模式做得到的——不用開 Code 節點,不用寫函式。expression 裡能用的 JavaScript 內建函式(Number、String、Boolean、Math.round、Date、字串的 .toUpperCase()、.trim()、.split() 等)大多都能直接寫。
{{ $json.xxx }}。新手用這招最省事。Include Other Input Fields:新手最常踩雷的 toggle
這個 toggle 是 Set 節點最容易搞混的地方,值得單獨拎出來講。
| Toggle 狀態 | 行為 | Output 會有什麼 |
|---|---|---|
| Include Other Input Fields 打勾 | 保留 input 原本所有欄位,你設的 fields 會覆蓋(同名)或加上(新名) | 原本 5 個欄位 + 你新加的 2 個 = 7 個欄位 |
| Include Other Input Fields 關掉 | 只留你在 Fields to Set 裡明列的欄位,其他全丟掉 | 你設 2 個欄位 = 只有 2 個欄位 |
什麼時候用什麼?
- 加欄位、改欄位但想保留其他 → 打勾。這是最常見的用法。
- 大清洗——只想留三個欄位丟給下游 → 關掉,然後在 Fields to Set 明列你要的三個欄位。
- 安全考量——上游 API 回應裡有敏感欄位(token、password_hash),不想帶到下游 → 關掉,只挑安全的欄位放行。
email,那你的下游節點就永遠拿不到 email——這是新手最常見的「欄位不見」bug。輸出面板看到欄位少了,第一個先檢查這個 toggle。另外一個常見誤解:這個 toggle 只保留「當前 input item」的欄位;如果你想引用更早前幾個節點的 payload,還是要用 {{ $('節點名').item.json.xxx }}(見 FAQ 最後一題)。舊版介面這個 toggle 叫 Keep Only Set Fields(保留邏輯剛好相反:打勾=只留 set 的),v1 之後改叫 Include Other Input Fields(打勾=保留其他),語意直覺很多。注意 n8n 官方 docs 頁到今天仍寫舊字 Keep Only Set Fields,跟你在 UI 看到的字對不起來很正常;以 UI 字樣為準。
JSON 模式:重新規劃結構的利器
當你要做的不只是加幾個欄位,而是要把整個 JSON 結構重新設計——例如把扁平的欄位收成巢狀物件,Manual Mapping 就顯得笨重。這時 JSON 模式登場。
情境:上游吐扁平 JSON,你要送到某個 API,那 API 要求的 payload 是巢狀結構。假設上游是:
{
"id": "ORD-1234",
"firstName": "小明",
"lastName": "王",
"amount": 1500
}
但下游 API 要求的格式是:
{
"orderId": "ORD-1234",
"customer": {
"name": "王小明",
"vip": true
}
}
Manual Mapping 要處理巢狀比較彆扭;改用 JSON 模式一貼就搞定:
-
Mode 切到 JSON
節點最上方 Mode 下拉選 JSON。Fields to Set 消失,出現一個大文字框。
-
貼 JSON template
把下面這段整段貼進文字框:
{ "orderId": "{{ $json.id }}", "customer": { "name": "{{ $json.lastName }}{{ $json.firstName }}", "vip": {{ $json.amount > 1000 }} } }字串類的值要用引號包(
"{{ ... }}"),布林/數字類不用引號({{ $json.amount > 1000 }}直接是true或false)。 -
Include Other Input Fields 決定要不要保留原欄位
JSON 模式一樣有這個 toggle。多數情況下你貼 JSON 就是要重新規劃結構,所以會 關掉——只留 JSON template 裡定義的欄位。
-
Execute Node 檢查結構對不對
Output 面板會吐出你貼的 JSON 結構,expression 都已經被填成實際值。這時就可以接下游的 HTTP Request 節點打 API。
實例:把 API 回來的巢狀 JSON 整成 Sheet 一列
把上一節 Set 節點的功力串起來,做一個實際會用到的短流程。情境:你用 HTTP Request 打了某個訂單 API,回來的 JSON 是巢狀結構,但你要把它 append 進 Google Sheets 的訂單追蹤表(一列 4 欄)。
上游 HTTP Request 節點的回應:
{
"data": {
"user": {
"name": "王小明",
"email": "[email protected]"
},
"order": {
"id": "ORD-9527",
"amount": 2800
},
"meta": {
"ts": "2026-08-16T10:30:00Z"
}
}
}
Sheets 的 header:訂單編號 | 姓名 | 信箱 | 金額 | 時間 | VIP
中間放一個 Set 節點做整形:
-
Set 節點 Mode 選 Manual Mapping
因為要對應 Sheets 的固定欄位,一欄一欄設最清楚。
-
Include Other Input Fields 關掉
原本的巢狀結構帶到 Sheets 沒意義,關掉 toggle 只留下面設的六個欄位。
-
Add Field 六次,依序設好
逐欄對照 Sheets 的 header:
Name Type Value(Expression) 訂單編號String {{ $json.data.order.id }}姓名String {{ $json.data.user.name }}信箱String {{ $json.data.user.email }}金額Number {{ $json.data.order.amount }}時間String {{ $json.data.meta.ts }}VIPString {{ $json.data.order.amount > 1000 ? 'VIP' : '一般' }} -
Execute Node 檢查扁平結構
Output 應該是純扁平的 6 個欄位:
{ 訂單編號: "ORD-9527", 姓名: "王小明", 信箱: "...", 金額: 2800, 時間: "...", VIP: "VIP" }。 -
接 Google Sheets Append 節點
Sheets 節點 Data Mode 選 Map Each Column Below,因為欄位名字已經完全對齊 Sheets header,可以直接拖左邊面板的欄位到 Sheets 節點對應的輸入框——不用再打一次 expression。
這就是 Set 節點的典型工作模式:「把上游丟過來的亂七八糟 JSON,梳成下游好吃的樣子」。Sheets、Slack、Notion、Airtable 這些節點都很挑欄位格式,中間放一個 Set 讓資料整齊,下游節點就好設得多。
Set 節點 vs Function vs Code:什麼時候用哪個
n8n 裡有三個節點都能「整形資料」,但用途不同。你可能在舊教學看過 Function 節點,這裡一次講清楚:
| 節點 | 寫程式嗎 | 能力 | 什麼時候用 |
|---|---|---|---|
| Set (Edit Fields) | 不用 | 加/改/刪欄位、簡單 expression、型別轉換 | 90% 的資料整形。優先選這個,能不寫程式就不寫 |
| Function(已於 v0.198.0 合併進 Code) | 要寫 JavaScript | 能 loop、能呼叫少數 helper、比 Set 靈活但受限 | 不要用了。v0.198.0(2022 年年中)起被 Code 節點取代;新拉節點面板已找不到,只有 import 舊 workflow 才看得到 |
| Code(新版) | 要寫 JavaScript 或 Python | 完整程式邏輯——loop、if / else、call npm module、複雜計算 | Set 做不到的複雜邏輯。詳細在 第 20 章 |
怎麼選?先問自己:「這件事 Set 能做嗎?」能就用 Set,不能才升級 Code。Set 節點視覺化、看得懂、不易寫錯、執行快;Code 節點強大但要寫程式、要處理錯誤、非工程師接手比較痛苦。
幾個 Set 節點的進階小技巧
1. 用 dot notation 加巢狀欄位(Manual Mapping 模式)
Manual Mapping 模式其實也能產出巢狀結構,訣竅是 Name 欄位用「點」串路徑:
- Name =
customer.name, Value ={{ $json.firstName }} - Name =
customer.email, Value ={{ $json.email }}
Output 會是:{ customer: { name: "小明", email: "..." } }。省得切 JSON 模式。
2. 一次覆蓋多筆 items
Set 節點跟其他節點一樣,會自動對每一筆 item 執行一次。所以你不用寫 loop——上游丟 10 筆進來,Set 就會產出 10 筆整形後的 output。$json 在每一輪自動指向「當前這一筆 item」。
3. 用 Continue On Fail 讓錯誤 item 不擋整條流
Set 節點右上角 Settings 齒輪裡有 Continue On Fail。某一筆 item 的 expression 執行失敗(例:某欄位不存在導致 undefined.foo)時,如果沒開這個,整條 workflow 直接紅字停下。開了以後那筆 item 會標成 error 但流繼續跑,你可以在 output 看哪幾筆壞掉、其他繼續往下游走。
4. Set 節點也可以放在流程開頭當「假資料產生器」
還沒有真實 trigger、想先測後面幾個節點的邏輯?拉一個 Manual Trigger + Set 節點,Set 節點 Mode 選 JSON、貼一段假資料 JSON、Include Other Input Fields 關掉——這樣按 Execute Workflow 就會有一筆假資料流下去。debug 神器。
delete item.json.欄位名。
常見卡關與怎麼救
| 症狀 | 原因 | 怎麼救 |
|---|---|---|
| Set 完欄位不見了(原本有 email,下游拿不到) | Include Other Input Fields 沒打勾(或舊版 Keep Only Set Fields 開了),你也沒在 Fields to Set 明列 email | 打開 Include Other Input Fields toggle,或把要留的欄位都手動 Add Field 一遍 |
Expression 拿到 undefined |
欄位路徑打錯——例如上游其實是 $json.name,你寫成 $json.data.user.name |
先按 Execute Node 上游節點,看 output 面板實際 JSON 長什麼樣,照抄路徑;或者在左邊 input 面板點欄位名讓 n8n 自動填 |
| 加了欄位但下游節點沒吃到 | 下游節點的 expression 還在引舊欄位名(例:你把 email 改叫 customer_email,但下游還在打 $json.email) |
rename 欄位後,記得同步更新所有下游節點的 expression。改名字是有連鎖影響的 |
| 欄位名字有空格或中文,expression 找不到 | JavaScript dot notation($json.欄 名)不支援空格 |
用中括號寫法:{{ $json['欄 名'] }}、{{ $json['姓 名'] }}。中括號可以吃任何字元 |
Value 明明打數字,Output 卻是字串 "123" |
Fields to Set 的 Type 設成 String,或 JSON 模式裡值用引號包了 | Manual Mapping:Type 改 Number;JSON 模式:值不要用引號 "amount": {{ $json.amount }};或加型別轉換 {{ Number($json.amount) }} |
| 切換模式後所有欄位不見 | Manual Mapping 跟 JSON 模式的設定不共用。切模式=清空 | Ctrl+Z 復原切回原模式;或決定好模式後再開始設欄位 |
JSON 模式跳紅字 Invalid JSON |
字串欄位忘記用引號包、或多逗號少逗號 | 把 JSON 貼到 JSON validator(jsonlint.com)檢查;expression {{ }} 也要放在合法 JSON 位置,字串類要用引號 "{{ ... }}" |
| Manual Mapping 加了一堆欄位介面卡 | Set 節點欄位太多(>50 個)時介面渲染會慢 | 改用 JSON 模式:50 個欄位在 JSON 文字框裡是很小的一坨,比 50 張視覺化卡片流暢 |
常見問題
Set 節點會影響 execution time 嗎?
一個 Set 節點能設幾個欄位?有沒有上限?
Set 節點跟 Code 節點差在哪?我什麼時候該升級?
新版介面為什麼把 Set 改名叫 Edit Fields?
Set 節點能不能對「陣列」欄位做整形?例如把 tags: ["a","b","c"] 變成 tags: "a, b, c"?
tags、Type = String、Value = {{ $json.tags.join(', ') }}。反過來想把字串切成陣列:{{ $json.csv.split(',') }}、Type 選 Array。單一 item 內的陣列處理 Set 都能做;但如果是「把整個 items 陣列展開或合併」(例:一筆 item 展開成三筆、或三筆合併成一筆),那要用 第 16 章的 Split In Batches / Merge 節點,或直接寫 Code。Set 節點裡的 $now 是什麼時區?寫進 Sheets 會不會跑掉?
$now 是 n8n Luxon DateTime 物件,預設用 n8n instance 的時區(如果你的 n8n 部署在 Asia/Taipei 就是台北時間)。直接寫進 Sheets 有時 Sheets 會自作聰明轉時區。建議做法:Value 用 {{ $now.toFormat('yyyy-MM-dd HH:mm:ss') }} 直接產字串,Type 選 String,Sheets 那邊那欄先設「純文字」格式——這樣什麼時區、什麼格式都是你自己控制,最穩。Include Other Input Fields 打勾時,如果我 set 的欄位名跟原欄位撞名,會發生什麼事?
email: "[email protected]",你在 Set 節點加一個 Field,Name = email、Value = 「已隱藏」——output 的 email 就是「已隱藏」。這是很方便的「就地改值」用法,例如把敏感欄位遮蔽、或把某欄的值標準化({{ $json.email.toLowerCase() }})。撞名時 set 值永遠贏,不會出錯也不會警告,直接覆蓋。能不能在 Set 節點裡引用「另一個節點」的資料,而不是上一個節點?
{{ $('節點名稱').item.json.欄位 }} 就能拉任何前面節點的資料,不只上一個。例:workflow 開頭有一個 Webhook 節點名叫 Webhook,中間跑了三個節點,最後一個 Set 節點想同時拉 Webhook 的原始 payload 和上一步的計算結果——Value 可以寫 {{ $('Webhook').item.json.customer_id }} - {{ $json.result }}。這在複雜 workflow 裡是常用手法,比每一步都用 Set「保留欄位」乾淨得多。細節在 第 14 章expression 篇有完整範例,第 19 章的 subworkflow 也會用到類似技巧。