یک ربات کوچک و ساده نشسته روی زمین و چند شکل هندسی رهاشده (مثل کروشه و براکت) رو مقابلش نگاه می‌کنه

دستکاری JSON در n8n: راهنمای گام‌به‌گام با Set و Code Node

دستکاری JSON در n8n یعنی تغییر شکل داده‌ای که یک گره به گره‌ی بعدی می‌ده. برای تغییر‌های ساده از گره‌ی Set استفاده کن، برای منطق پیچیده‌تر از گره‌ی Code. انتخاب بین این دو تا شکل داده‌ات بستگی داره، نه به سلیقه‌ی خودت.

اگه تا حالا با n8n کار کرده باشی، حتماً یک جایی رسیدی که داده‌های ورودی یک گره با چیزی که گره‌ی بعدی انتظارش رو داره، جور در نمیاد. خطای قرمز، اسم فیلد اشتباه، یا یک آرایه‌ی تودرتو که باید اول بازش کنی. اینجاست که بیشتر ورک‌فلوها گیر می‌کنن: نه چون سرویس قطع شده، بلکه چون شکل داده با چیزی که ورک‌فلو انتظارش رو داره، یکی نیست.

JSON دقیقاً کجای n8n وارد کار می‌شه؟

هر خروجی که از یک گره n8n به گره‌ی بعدی می‌رود، یک آرایه JSON است — حتی اگر روی صفحه به شکل جدول یا متن ساده نشونش داده باشی. توی پنل خروجی هر گره می‌تونی نمای JSON رو انتخاب کنی و خروجی خام رو ببینی. وقتی به فرمت ورودی یکی از گره‌ها اطمینان نداری، یا می‌خوای فیلدی بسازی/حذف کنی که از API نیومده، وقتشه دستکاری کنی.

چطور با گره‌ی Set فیلد‌های JSON رو تغییر بدیم؟

گره‌ی Set (که توی نسخه‌های جدید n8n بهش می‌گن Edit Fields) برای کارهای ساده کافیه: اضافه‌کردن یک فیلد جدید، تغییر مقدار یک فیلد موجود، یا حذف فیلدهای اضافی. توی حالت Expression می‌تونی از مقادیر گره‌های قبلی استفاده کنی — مثلاً {{ $json.customer.name }}. محدودیت Set اینجاست که نمی‌تونی توی یک فیلد لوپ بزنی یا شرط پیچیده بگذاری — اینجاست که Code Node وارد می‌شه.

Code Node دو حالت اجرا داره — فرقشون رو جدی بگیر

گیج‌ترین خطای مبتدی‌ها توی Code Node اینه که فرق دو حالت اجرا رو قاطی می‌کنن. بالای هر Code Node یک کشویی هست با دو گزینه:

  • Run Once for All Items (پیش‌فرض): کد فقط یک بار اجرا می‌شه و به همه‌ی آیتم‌های ورودی یکجا دسترسی داری — با $input.all() که آرایه‌ای از همه‌ی آیتم‌ها برمی‌گردونه.
  • Run Once for Each Item: کد به تعداد آیتم‌های ورودی اجرا می‌شه — در هر اجرا، فقط به همون یک آیتم با $json یا $input.item دسترسی داری.

گیج رایج که اینجا زیاد دیدیم: نوشتن items به‌جای $input.all() (مال نسخه‌های قدیمی‌تر). اگر مقاله‌ای دیدی که از items مستقیم استفاده کرده، ممکنه روی نسخه‌ی قدیمی نوشته شده — در نسخه‌های فعلی n8n همیشه از $input استفاده کن.

مثال کد برای حالت «Run Once for All Items» (فیلترکردن سفارش‌های پرداخت‌شده):

const allItems = $input.all();
const paid = allItems.filter(item => item.json.status === 'paid');
return paid;

و مثال کد برای حالت «Run Once for Each Item» (ساخت یک فیلد جدید روی هر آیتم):

return {
  json: {
    ...$json,
    fullName: $json.firstName + ' ' + $json.lastName
  }
};

فرمت خروجی هم به حالت اجرا بستگی داره: توی حالت «All Items» باید یک آرایه از آیتم‌ها برگردونی که هرکدوم به شکل { json: {...} } باشه؛ توی حالت «Each Item» برگردوندن یک آبجکت کافیه و n8n خودش اون رو داخل json می‌پیچه. توی حالت Each Item از $json یا $input.item استفاده کن؛ $input.all() مال حالت All Items است. قاطی‌کردن این دو، رایج‌ترین دلیل خروجی خالی یا ناقص از Code Node است.

یک محدودیت واقعی که کمتر کسی بهش می‌رسه: sandbox همه‌چی استاندارد جاوااسکریپت رو نداره

Code Node توی n8n در یک sandbox اجرا می‌شه که به دلایل امنیتی، به تمام API‌های استاندارد جاوااسکریپت دسترسی نداره. یک نمونه‌ی شناخته‌شده: کلاس URL جاوااسکریپت در دسترس نیست — اگه بنویسی new URL(someLink)، خطایی مثل Cannot find name 'URL' می‌گیری. برای پارس کردن یک URL داخل Code Node باید یا دستی (با split و regex) کار کنی — همون روشی که توی ورک‌فلوی واقعی خودکارا پایین استفاده شده (بخش بعد) — یا از یک گره‌ی پیشین برای پارس کردن URL استفاده کنی. این رو خودمون تجربه کردیم: روی نسخه‌ی self-hosted خودکارا new URL() توی Code Node کار نکرد. اگه نسخه یا تنظیمات اجرای کد n8n تو فرق داره، قبل از تکیه روی هر API استاندارد یک تست کوچک بزن.

آرایه‌های تودرتو: قبل از Code Node سراغ Split Out و Aggregate برو

وقتی یک فیلد در داده‌هات خودش یک آرایه است (مثلاً لیست محصولات یک سفارش)، قبل از نوشتن یک حلقه‌ی دستی داخل Code Node، اول گره‌ی «Split Out» رو امتحان کن. این گره یک فیلد آرایه‌ای رو می‌گیره و هر عضوش رو به یک آیتم جدا تبدیل می‌کنه — یعنی هر محصول رو جداگانه با گره‌های بعدی پردازش کنی — درست مثل وقتی که یک حلقه‌ی دستی توی Code می‌نویسی.

بعد از پردازش، اگر لازمه نتیجه رو دوباره جمع کنی (مثلاً یک آرایه جمع‌شده از قیمت‌ها)، گره‌ی «Aggregate» رو اضافه کن — دقیقاً عکس کار Split Out رو انجام می‌ده و چند آیتم رو دوباره توی یک آیتم جمع می‌کنه. این دو گره، برای بیشتر سناریوهای دستکاری آرایه تودرتو، جایگزین سریع‌تر و قابل‌خواندن‌تر از یک Code Node دستی هستند. Code Node رو برای منطقی که این دو گره پوشششون نمی‌دن (مثلاً شرط پیچیده یا محاسبه‌ی دلخواه) نگه دار.

خطاهای رایج JSON در n8n و راه‌حلشون

خطاعلتراه‌حل
Cannot read property of undefinedفیلد توی یکی از آیتم‌ها وجود ندارهقبل از دسترسی با شرط ?. وجود فیلد رو چک کن
Cannot find name ‘URL’استفاده از new URL() در sandbox پیش‌فرضپارس دستی با split/regex یا استفاده از گره‌ی مخصوص پارس URL
خروجی خالی از Code Nodeفرمت خروجی با حالت اجرا جور نیستدر حالت All Items آرایه‌ای از { json: {...} } برگردون؛ در حالت Each Item یک آبجکت
داده توی گره بعدی خالی می‌رسهاسم فیلد توی Set با منبع واقعی یکی نیستخروجی گره‌ی قبلی رو توی پنل n8n (تب Output) باز کن و اسم دقیق فیلد رو کپی کن

یک نمونه واقعی از کد Code Node توی یکی از ورک‌فلوهای خودکارا

این کد رو مستقیم از یکی از ورک‌فلوهای داخلی خودکارا برداشتیم (پاک‌سازی پست‌های حذف‌شده). وقتی یک URL خام وارد می‌شه، این کد فقط اسلاگ آخرش رو بیرون می‌کشه — بدون new URL()، چون همون‌طور که گفتیم در sandbox در دسترس نیست. این کد در حالت Run Once for Each Item اجرا می‌شه، برای همین فقط یک آبجکت ساده برمی‌گردونه:

const raw = ($json.URL || $json.url || $json.Url || '');
let rawStr = raw.toString().trim();
rawStr = rawStr.replace(/[u200b-u200fu202a-u202eufeff]/g, '').trim();

let slug = '';
try {
  const noProtocol = rawStr.replace(/^https?:///i, '');
  const noDomain = noProtocol.replace(/^[^/]+/, '');
  const cleanPath = noDomain.split('?')[0].split('#')[0];
  const parts = cleanPath.split('/').filter(Boolean);
  slug = parts.length ? parts[parts.length - 1] : '';
} catch (e) {}

return { url: rawStr, slug };

سه نکته‌ی این کد که توی پروژه‌های واقعی زیاد تکرار می‌شن:

  • چند نام جایگزین برای یک فیلد — $json.URL || $json.url || $json.Url — چون داده از منابع مختلف می‌آد و اسم ستون همیشه یکی نیست.
  • پاک‌سازی کاراکترهای نامرئی — کاراکترهایی که از کپی‌پیست متن فارسی می‌افتد و مقایسه‌ی رشته‌ای شکست می‌ده.
  • try/catch دور استخراج — یک ردیف خراب توی شیت کل ورک‌فلو رو متوقف نمی‌کنه.

اگر داده‌هات از یک سفارش ووکامرس می‌آد و لازمه همین جا دستکاری کنی، حواست باشه که قیمت و total توی payload ووکامرس رشته‌ان نه عدد؛ قبل از هر محاسبه باید تبدیلشون کنی (مثلاً با Number($json.total)). ساختار کامل payload سفارش رو توی راهنمای اتصال n8n به ووکامرس ببین.

سوال‌های متداول

می‌شه بدون Code Node JSON رو تغییر داد؟
برای کارهای ساده آره، برای منطق پیچیده یا حلقه نه.

فرق JSON و Object چیه؟
JSON فرمت متنی برای انتقال داده‌هاست؛ Object ساختار داده توی حافظه. n8n وقتی از API جواب می‌گیره یا به API دیگه می‌فرسته، بین این دو تبدیل می‌کنه.

آرایه‌ی تودرتو رو چطور به یه آرایه‌ی ساده‌تر تبدیل کنیم؟
اگر فقط می‌خوای شکل رو مسطح کنی، گره‌ی Split Out رو امتحان کن. اگر پردازش پیچیده یا شرطی لازمه، Code Node با حلقه .map() انعطاف‌پذیرتره.

اگه سروکارت با n8n جایی گیر کرده که هر بار یک ورک‌فلو با یک خطای JSON جدید می‌خوره، لزومی نیست خودت تنها پشت سرش بمونی؛ با تیم خودکارا تماس بگیر.

نمی‌خواهی خودت بسازی؟ اگه ترجیح می‌دی این ورک‌فلو رو یه تیم برات پیاده کنه، نه خودت، مشاوره‌ی پیاده‌سازی هوش مصنوعی در کسب‌وکار رو ببین.

نوشته های مرتبط