فایل بزرگ JSON باز نمیشود؟ ابزار مناسب را بر اساس حجم انتخاب کنید
جمعبندی: خروجیهای JSON چند ده مگابایتی اغلب ویرایشگرهای متنی و ابزارهای آنلاین را قفل میکنند، حال آنکه خود پارس تنها چند صد میلیثانیه طول میکشد. ما زمان و حافظه هر مرحله را روی نمونهای ۴۵ مگابایتی با ۵۰۰ هزار رکورد اندازه گرفتیم، نشان دادیم هزینه واقعی در تعداد خطوط و گرههاست و جدول انتخاب ابزار بر اساس حجم فایل ارائه کردیم: مشاهده آنلاین، استخراج خط فرمانی، پردازش جریانی و برنامه دسکتاپ.

یک فایل JSON چهل و پنج مگابایتی در ۲۴۹ میلیثانیه پارس میشود. نیم دقیقه انتظار از رندر پنج میلیون خط متن و سه و نیم میلیون گره درخت میآید. اگر این دو را با هم اشتباه بگیرید، هر بار مقصر اشتباه را سرزنش میکنید.
یک: اول اندازه بگیرید — پارس هرگز گلوگاه نیست
روی خروجی .json چند ده مگابایتی دابلکلیک میکنید، ویرایشگر سی ثانیه میچرخد، و غریزه میگوید «پارس JSON کند است». اندازهگیریها برعکس را میگویند. روی دستگاه ما (Node 22) نمونهای با ۵۰۰ هزار رکورد و هر کدام پنج فیلد (id، email، active، score، tags) ساختیم؛ ۴۵ مگابایت در حالت فشرده:
| عملیات | نتیجه اندازهگیری |
|---|---|
JSON.parse کامل |
۲۴۹ میلیثانیه |
JSON.stringify(data, null, 2) — خروجی مرتب |
۲۱۵ میلیثانیه |
| متن مرتبشده | ۷۱ مگابایت، ۵٬۰۰۰٬۰۰۱ خط |
| مجموع گرههای درخت (رکوردها + فیلدها) | حدود ۳٬۵۰۰٬۰۰۱ |
| RSS فرایند Node بعد از پارس | ۳۱۳ مگابایت (حدود ۷ برابر حجم فایل) |
پارس در یکچهارم ثانیه تمام شد. پارسر پیش از آنکه ماوس را رها کنید کارش تمام بود. همه ثانیههای بعدی در لایه «نمایش نتیجه به انسان» گذشت: ویرایشگر متنی باید پنج میلیون خط را صفحهبندی کند، هایلایت سینتکس اعمال کند و بافر undo نگه دارد؛ نمایشگر درختی باید برای تکتک ۳٫۵ میلیون گره عنصر DOM بسازد — و مرورگرها حدود صد هزار گره دیگر نفس نمیآورند و خیلی پیش از یک میلیون پاسخگویی را از دست میدهند.
این نتیجه به جهتی کاملاً متفاوت اشاره میکند: با رندر نجنگید؛ ابزاری بردارید که همهچیز را رندر نمیکند.
دو: چرا قفل میشود — تعداد خطوط و گرهها هزینه واقعی است
حجم فایل فقط ظاهر ماجراست. دو عدد مشتقشده ابزارها را میشکنند:
- تعداد خطوط. JSON فشرده ۴۵ مگابایتی پس از مرتبسازی پنج میلیون خط میشود. هر بخشی را که میبینید، ویرایشگر ابتدا باید ساختار خطوط کل فایل را بسازد، وضعیت هایلایت را حل کند و بافر تخصیص دهد — هزینه متناسب با کل خطوط است.
- تعداد گرهها. نیم میلیون رکورد × (یک شیء + پنج فیلد) میشود ۳٫۵ میلیون گره. هر نمایشگری که قبل از نمایش کل درخت را بسازد، چه یک شاخه را باز کنید چه همه را، همان حافظه و زمان را میپردازد.
دو نتیجه برخلاف شهود از آن میآید. مرتبکردن قبل از نگاه کردن مضرّ است — فایل از ۴۵ به ۷۱ مگابایت بزرگ میشود و خطوط چهل برابر؛ فشار خالص اضافی بر ابزار. هل دادن فایل با cat به ترمینال هم مضرّ است — بافر اسکرول گلوگاه جدید میشود؛ برای بایتهای ابتدایی head -c 2000 کافی است.
سه: انتخاب ابزار بر اساس حجم — جدول تصمیم
حجمهای مختلف ابزارهای کاملاً متفاوتی میخواهند. با ترکیب اندازهگیریهای بالا و راهنماهای منتشرشده (OpenFormatter ناحیه آسایش ابزارهای آنلاین را ۲ تا ۵ مگابایت میداند؛ PureJSON حافظه پس از پارس سند ۵۰۰ مگابایتی را ۲ تا ۴ گیگابایت برآورد میکند) این جدول به دست میآید:
| حجم فایل | انتخاب اول | چرا |
|---|---|---|
| < 2 MB | هر ابزار آنلاینی | دسترسی فوری؛ نمایش درختی + اعتبارسنجی به سبک /parse در یک گام |
| 2 – 20 MB | ویرایشگر محلی (VS Code) یا ابزار محلی در مرورگر | ابزارهای آنلاین شروع به افت میکنند؛ پردازش محلی چیزی نمیفرستد |
| 20 – 100 MB | اکتشاف با jq در خط فرمان + نمایشگر درختی مجازیسازیشده | ویرایشگرها کند میشوند؛ jq هر قطعهای را در چند ثانیه استخراج میکند |
| 100 MB – 1 GB | jq --stream / ijson، پردازش جریانی |
حافظه پارس معمولی تا ~۷ برابر فایل رشد میکند؛ جا نشد، جریانی کار کن |
| > 1 GB یا پیوسته الحاقی | تغییر قالب: NDJSON / CSV / Parquet | یک آرایه غولآسا باید کامل پارس شود تا اولین رکورد به درد بخورد؛ مشکل خودِ قالب است |
ابزار /parse این سایت پله اول را پوشش میدهد: نمایش درختی و اعتبارسنجی. فایلهای بزرگتر مالِ برنامه دسکتاپ هستند تا دهها مگابایت هرگز در صفحه وب چسبانده نشوند.
چهار: فایل را باز نکنید — اول درباره ساختارش بپرسید
با یک JSON بزرگ ناشناس، اولین حرکت باز کردن نیست، بلکه چند ثانیه وقت گذاشتن برای شناخت شکل آن است. jq در حدود ۲۰۰ میلیثانیه به سه پرسش پاسخ میدهد:
# در رأس آرایه است یا شیء؟ چند رکورد؟
jq 'if type == "array" then {type: "array", count: length} else {type: "object", keys: (keys|length)} end' huge.json
# اولین رکورد چه شکلی است (فقط یکی، بدون سیل)؟
jq '.[0]' huge.json | head -40
# همه نام فیلدها (از رکورد اول)
jq '.[0] | keys' huge.json
وقتی ساختار معلوم شد، بیشتر درخواستها به «استخراج یک فیلد» فرو میکاهند — اصلاً نیازی به باز کردن فایل نیست. مثلاً برای گرفتن ایمیل هر کاربر:
jq -r '.[].email' huge.json | less
# فیلتر را رویش بگذارید
jq -r '.[] | select(.active == true) | .email' huge.json
قاعده ساده است: برای «دیدن»، نمایشگری با رندر مجازیسازیشده؛ برای «جستوجو و استخراج»، jq. این دو نقش را در یک ابزار مخلوط نکنید.
پنج: پرتگاه حافظه — حالت معمولی در برابر جریانی، ۱۵۰ برابر اختلاف
روی همان نمونه ۴۵ مگابایتی، /usr/bin/time -v اوج حافظه jq را در دو حالت اندازه گرفت:
| حالت | دستور | اوج حافظه (RSS) | زمان |
|---|---|---|---|
| معمولی (بارگذاری کامل) | jq '.[0].email' sample.json |
۵۴۲ مگابایت | ۰٫۷ ثانیه |
| جریانی | jq --stream 'select(.[0][1]=="email") | .[1]' sample.json |
۳٫۶ مگابایت | ۲٫۵ ثانیه |
حالت معمولی کل فایل را میخواند و گراف اشیاء میسازد؛ اوج ۵۴۲ مگابایت قاعده «گراف اشیاء ≈ ۷ تا ۱۲ برابر حجم متن» را تأیید میکند. --stream ورودی را توکن به توکن مصرف میکند و حافظه را در چند مگابایت ثابت نگه میدارد — به بهای زمان کل بیشتر. فراتر از مرز گیگابایت، همین تفاوت «کار میکند» و «توسط OOM killer کشته شد» را جدا میکند:
# برای فایلهای بزرگتر از حافظه: --stream تنها حالتی است که هرگز همه را بار نمیکند
jq --stream -n 'fromstream(1|truncate_stream(inputs))' huge.json
معادل پایتونی ijson است: ijson.items(f, 'item') عناصر آرایه را یکییکی با همان حافظه ثابت تحویل میدهد. بهای مشترک این ابزارها چشمپوشی از دسترسی تصادفی است — جریان فقط یک گذر رو به جلو است و گذر دوم یعنی خواندن دوباره فایل.
شش: مرورگر تا کجا میرود — مرزهای پردازش محلی
ابزارهای آنلاین قابل استفادهاند، اما در محدوده. یک تب مدرن مرورگر حدود ۱ تا ۴ گیگابایت حافظه دارد؛ فایل ۴۵ مگابایتی که به گراف و درخت تبدیل شود معمولاً سرپا میماند. چند صد مگابایت لبه پرتگاه است. هنگام انتخاب نمایشگر آنلاین سه چیز را مطالبه کنید:
- پردازش بهصورت محلی انجام میشود (محتوای چسباندهشده هرگز به سرور فرستاده نمیشود) که هم دادهها را محافظت میکند هم زمان آپلود را — همه ابزارهای این سایت کاملاً در مرورگر اجرا میشوند و آفلاین کار میکنند؛
- پارس در Web Worker اجرا میشود — نخ اصلی منجمد نمیشود و قفلشدن بهای یک تب دارد، نه کل مرورگر؛
- درخت مجازیسازیشده یا تنبل است — شاخههای بسته تقریباً رایگاناند و فقط بازشده رندر میشود.
در این سایت: /parse برای اکتشاف ساختار و یافتن خطا در فایلهای تا چند ده مگابایت مناسب است؛ بیشتر از آن، jq یا برنامه دسکتاپ، و مرورگر فقط برای قطعههای کوچک.
هفت: قالب درست، نصف مشکلات را حذف میکند
اگر بر نحوه تولید فایل اثر میگذارید، نمایشگر بهتر درمان اشتباه است — کاری کنید فایل به «یک آرایه غولآسا» تبدیل نشود:
- NDJSON/JSONL: هر خط یک رکورد. الحاق، فایل را بازنویسی نمیکند و
head،grep،tail،splitمستقیماً کار میکنند؛ فایل بریدهشده فقط خط آخر را از دست میدهد. در کتابچه JSONL ما رویه کامل رفع اشکال خطوط شکسته آمده است. - خروجی صفحهبندیشده: APIای که ۱۰۰ هزار رکورد برمیگرداند باید پارامترهای صفحهبندی بپذیرد — ۱۰۰ تا در هر بار برای هر دو طرف دلپذیرتر است.
- دادههای جدولی JSON نیستند: هر خط یک رکورد با فیلدهای ثابت و بدون تودرتو — این یک جدول است. CSV یا Parquet کوچکترند و اکوسیستم غنیتری دارند.
عددی که ارزش به خاطر سپردن دارد: آرایه ۵۰۰ هزار رکوردی را از وسط ببرید، نیمه اول هنوز فایل NDJSON معتبری است (نیمی از رکوردها زندهاند)، اما آرایه یکپارچه معادل کاملاً از دست میرود. بازیابی ۵۰۰ رکورد از ۵۰۱ بهتر از صفر است.
هشت: چکلیست
- ابتدا با
jq '.[0] | keys'یا نمونه ۵۰۰ رکوردی ساختار را کاوش کنید؛ - هرگز صرفاً برای باز کردن، مرتب نکنید — دوبرابر شدن خطوط فقط کندترش میکند؛
- زیر ۲ مگابایت: نمایش درختی آنلاین؛ بالای ۲۰ مگابایت: خط فرمان؛ بالای ۱ گیگابایت: همیشه
--streamیا ijson؛ - مطمئن شوید ابزار آنلاین محلی پردازش میکند (محتوای چسباندهشده مرورگر را ترک نمیکند)؛
- اگر مولد فایل دست شماست، به NDJSON یا صفحهبندی مهاجرت کنید و آرایههای غولآسا را در منبع حذف کنید.
پرسشهای پرتکرار
چرا ویرایشگر دهها ثانیه برای باز کردن JSON میگیرد در حالی که برنامه آن را در ۲۰۰ میلیثانیه پارس میکند؟
پارس کد بومی است که متن را به ساختار داده تبدیل میکند: ۲۴۹ میلیثانیه برای نمونه ۴۵ مگابایتی ما. ویرایشگر روی ارائه میماند: پنج میلیون خط برای صفحهبندی، هایلایت و بافر undo؛ درخت DOM برای ۳٫۵ میلیون گره میسازد. نمایشگر مجازیسازیشده یا استخراج مستقیم با jq همه اینها را دور میزند.
jq روی JSON بالای ۱ گیگابایت سرریز حافظه میکند؟
در حالت معمولی بله: کل سند را بار میکند و گراف اشیاء تا ۷ تا ۱۲ برابر حجم فایل بالا میرود. با --stream ورودی توکن به توکن مصرف میشود: آزمایش ۴۵ مگابایتی ما اوج ۳٫۶ مگابایت داشت و حافظه مستقل از حجم فایل صاف میماند — به بهای فقط یک گذر ترتیبی.
ابزارهای آنلاین JSON چه حجم فایلی را تحمل میکنند؟
بیشترشان تا ۲ تا ۵ مگابایت راحتاند و پس از ۱۰ مگابایت آشکارا افت میکنند. سقف سخت، حافظه تب است (حدود ۱ تا ۴ گیگابایت)، اما در چند ده مگابایت انتظار پارس و ساخت درخت آزاردهنده میشود. بالای ۲۰ مگابایت سراغ ابزار محلی یا خط فرمان بروید.
چطور مقدار یک فیلد را در JSON عظیم ببینم؟
با jq استخراج کنید، بدون باز کردن فایل: jq -r '.[].email' huge.json همه ایمیلها را چاپ میکند؛ با فیلتر jq -r '.[] | select(.active == true) | .email'. برای رکوردهای اول jq '.[0:5]' huge.json — چندین مرتبه سریعتر از باز کردن فایل.
مرتبکردن قبل از باز کردن کمک میکند؟
نه. مرتبسازی ۴۵ مگابایت فشرده را به ۷۱ مگابایت و یک خط را به پنج میلیون تبدیل میکند و برای ویرایشگر و نمایشگر فقط بار خالص میافزاید. مرتبسازی را برای چیزی نگه دارید که انسانی قرار است بخواند — و فقط وقتی فایل به اندازه کافی کوچک است.