رکوردهای JSON را به ردیفهای صفحهگسترده تبدیل کنید
یک شیء JSON، آرایهای از اشیا یا آرایهای از آرایهها را به یک فایل CSV یا جداشده با تب با کدگذاری UTF-۸ تبدیل میکند. میتواند مسیرهای تودرتوی اشیا را مسطح کند، بهطور پیشفرض از سلولهای فرمولمانند صفحهگسترده محافظت میکند و هرگز منبع را آپلود نمیکند.
یک شیء JSON، آرایهای از اشیا یا آرایهای از آرایهها تا ۲۰ مگابایت. فقط در همین تب تجزیه میشود.
چگونگی کار
این ابزار چه چیزی را محاسبه میکند
اختلاف JSON و CSV بر سر علائم نگارشی نیست؛ بر سر شکل است. JSON میتواند اشیا و آرایهها را در هر عمقی تودرتو کند، فیلدی را از یک رکورد جا بیندازد و اعداد، مقادیر بولی و null را بهعنوان نوعهای جداگانه نگه دارد. CSV مستطیلی از سلولهای متنی است. بنابراین تبدیل میان آن دو به پاسخی اعلامشده برای سه پرسش نیاز دارد: چه چیزی یک ردیف به حساب میآید، کدام سرستونها وجود دارند، و بر سر مقداری که از پیش متن مسطح نیست چه میآید.
این ابزار آن تصمیمها را آشکار میکند. فقط ساختارهای سطح بالایی را میپذیرد که مدل ردیفی صادقانهای دارند، یک سرستون پایدار را در کل مجموعه کشف میکند و مقادیر تودرتو را یا بهصورت JSON دستنخورده نگه میدارد یا مسیرهای اشیا را مسطح میکند. بایتهای دانلودشده سپس CSV یا TSV معمولی با کدگذاری UTF-۸ هستند، نه قالبی اختصاصی که برای بازخوانی به این سایت نیاز داشته باشد.
روش
مدل ردیف کاملاً از سطح بالا میآید:
| شکل JSON | تفسیر CSV |
|---|---|
{ "name": "Ada" } | یک شیء، یک ردیف |
[{ "name": "Ada" }, { "name": "Grace" }] | هر شیء یک ردیف است؛ کلیدها سرستوناند |
[["Ada", 36], ["Grace", 37]] | هر آرایهٔ داخلی یک ردیف است؛ سرستونها column_1، column_2 و به همین ترتیب هستند |
[{}, []] | رد میشود: ردیفها یک مدل مشترک ندارند |
42، null یا [] | رد میشود: جدول قابلاستفادهای وجود ندارد |
برای ردیفهای شیء، سرستون تنها از اولین رکورد گرفته نمیشود. دادهٔ واقعی API پراکنده است: ممکن است دهمین رکورد اولین رکوردی باشد که middleName یا invoice.vatNumber دارد. همهٔ اشیا پیمایش میشوند و اولین ظهور هر کلید آن را به انتهای سرستون اضافه میکند. این کار ترتیب را پیشبینیپذیر نگه میدارد، بیآنکه فیلدهای بعدی بیسروصدا گم شوند.
دو حالت تودرتو به پرسش متفاوتی پاسخ میدهند:
نگه داشتن بهصورت JSON در یک سلول مقدار تودرتو را بهصورت JSON فشرده حفظ میکند. مقداری مانند { "city": "Berlin", "postcode": "10115" } یک سلول نقلقولشده را اشغال میکند و میتوان آن را بدون حدس زدن اینکه کدام سرستونها به آن تعلق داشتهاند دوباره تجزیه کرد.
مسطح کردن اشیا به مسیرهای نقطهای address.city و address.postcode را ستونهای جداگانه میکند. نقطهها و بکاسلشهایی که از قبل در یک کلید هستند escape میشوند، بنابراین کلید لفظی address.city به address\.city تبدیل میشود و نمیتواند با شیئی به نام address که کلیدی به نام city دارد تداخل کند. آرایهها همچنان JSON میمانند، چون جایگاه صفر نام فیلد نیست.
وقتی هر ردیف مقادیرش را زیر سرستونهای پایدار دارد، قاعدهٔ CSV کوچک اما سختگیر است:
plain → plain
contains,comma → "contains,comma"
say "hello" → "say ""hello"""
two lines → "two
lines"
گیومهٔ درون فیلد دوتایی میشود. فیلدی که جداکننده، گیومه یا شکست خط دارد در گیومه قرار میگیرد. ردیفها با بازگشت نورد بهعلاوهٔ خطنو تمام میشوند، که قرارداد توصیفشده برای CSV است و نرمافزار صفحهگسترده آن را بهطور یکدست مدیریت میکند.
محافظت از فرمول در صفحهگسترده
CSV اطلاعات نوع ندارد. وقتی نرمافزار صفحهگسترده سلولی را ببیند که با =، +، - یا @ شروع میشود، ممکن است متن را بهجای داده، فرمول تفسیر کند. این وقتی مهم است که یک نام، یادداشت یا فیلد API درونریزیشده از کس دیگری آمده باشد: خروجی گرفتن از متن نامطمئن میتواند باز کردن صفحهگستردهٔ حاصل را به یک عمل تبدیل کند.
بنابراین محافظت بهطور پیشفرض روشن است. رشتهٔ JSON مانند "=2+2" به '=2+2 تبدیل میشود که صفحهگسترده آن را متن تلقی میکند. عدد JSON مانند -2 همان -2 میماند، چون واقعاً عددی است، نه رشتهای که معنایش استنباط میشود. سرستونها همین بررسی را میگیرند؛ نام فیلدها هم میتوانند دادهٔ نامطمئن باشند.
پیش از ادامهٔ مطلب
یک رکورد بعدی JSON فیلدی به نام email را معرفی میکند که رکورد اول نداشت. برای CSV چه باید بشود؟
در نقطهای که آن کلید برای اولین بار کشف میشود یک ستون email اضافه کنید و برای رکوردهایی که آن را ندارند سلول email خالی بنویسید. سرستون CSV باید کل جدول را توصیف کند، نه فقط ردیف اولش را. گرفتن کلیدهای تنها اولین شیء میانبری وسوسهانگیز است، چون سریع است و خروجیای با ظاهر معتبر میدهد، اما JSON پراکنده آن را به یک باگ از دست رفتن داده تبدیل میکند: فیلدی که بعداً ظاهر میشود بدون هیچ خطایی ناپدید میشود. بنابراین مبدل پیش از نوشتن سرستون، همهٔ ردیفها را برای اجتماع کلیدها اسکن میکند.
یک نمونهٔ کارشده
آزمون واحد این دو رکورد را با مسطح کردن، جداکنندهٔ کاما، نشانهٔ UTF-۸ و محافظت از فرمول روشن تبدیل میکند:
[
{
"name": "Ada, Ltd.",
"active": true,
"note": "Line 1\nLine 2",
"profile": { "city": "London" }
},
{
"name": "=2+2",
"active": false,
"profile": { "city": "Paris" }
}
]
نتیجه این است:
name,active,note,profile.city
"Ada, Ltd.",true,"Line 1
Line 2",London
'=2+2,false,,Paris
چهار جزئیات کار واقعی را انجام میدهند:
۱. profile.city یک مسیر مسطحشده است، نه برچسبی ساختگی.
۲. کاما و شکست خط فیلدهایشان را وادار به نقلقول میکنند.
۳. رکورد دوم note ندارد، بنابراین سلول note آن خالی است، نه اینکه Paris یک ستون به چپ بلغزد.
۴. =2+2 آپاستروف میگیرد چون از یک رشتهٔ JSON آمده؛ مقادیر بولی بهصورت متن نوعدار true و false میمانند.
فایل فیزیکی ۹۵ بایت است: ۹۲ بایت CSV قابلمشاهده و پایان خطها بهعلاوهٔ نشانهٔ سهبایتی UTF-۸. آزمون کل رشته را بایتبهبایت، هر چهار رقم خروجی، نام فایل و نوع MIME را تأیید میکند. آزمونهای جداگانه تغییر جداکنندهها، نامگذاری TSV، ستونهای اجتماعی، سلولهای JSON تودرتو، بخشهای مسیر escape شده، مقادیر غایب، پهنای خصمانه، پیشرفت و لغو را پوشش میدهند.
کاری که انجام نمیدهد
از JSON دلخواه یک پایگاه دادهٔ رابطهای استنتاج نمیکند. آرایههای تودرتو به جدولهای فرزند شکسته نمیشوند، اشیا با شناسههای حدسی به هم وصل نمیشوند و یک مقدار ابتدایی در سطح بالا در ستونی ساختگی به نام value پیچیده نمیشود. همهٔ اینها میتوانند عملیات مفیدی باشند، اما هر کدام به تصمیمی دربارهٔ طرحواره نیاز دارند که خود فایل فراهم نمیکند.
همچنین نمیتواند تمایز میان null و غایب را در CSV حفظ کند. هر دو سلول خالی میشوند، چون سلول خالی هیچ نوعی ندارد. نوشتن واژهٔ null یک مقدار را به بهای تمایزناپذیر شدن رشتهٔ واقعی "null" حفظ میکرد، بنابراین آن قرارداد باید توسط درونریزنده انتخاب شود، نه اینکه اینجا بیسروصدا تحمیل شود.
در نهایت، فرمولها، تاریخها یا اعداد با قالببندی محلی را ارزیابی نمیکند. عدد JSON با نحو اعشاری JSON نوشته میشود، رشته رشته میماند و صفحهگسترده پس از درونریزی تصمیم میگیرد چگونه نمایشش دهد. کار مبدل انتقال داده به ردیفهای پایدار است، بیآنکه آنچه را منبع گفته تغییر دهد.
مراحل انجام کار
- فایل را بهصورت UTF-۸ رمزگشایی کنید، نشانهٔ UTF-۸ ابتدای فایل را در صورت وجود دور بریزید و آن را با تجزیهگر داخلی JSON مرورگر تجزیه کنید. ورودی خالی یا از نظر نحوی نامعتبر با دلیل تجزیهگر رد میشود.
- مدل ردیف را از سطح بالا تعیین کنید. یک شیء یک ردیف است؛ آرایهای از اشیا چندین ردیف نامدار است؛ آرایهای از آرایهها چندین ردیف موقعیتی است. شکلهای ردیف مخلوط بهجای حدس زدن رد میشوند.
- برای ردیفهای شیء، اجتماع کلیدها را به ترتیب اولین مشاهده گردآوری کنید تا فیلدی که فقط در یک رکورد بعدی ظاهر میشود همچنان یک ستون پایدار بگیرد و ردیفهای قبلی در آنجا سلول خالی داشته باشند.
- وقتی مسطح کردن انتخاب شده، اشیای تودرتو را به مسیرهای نقطهای escape شده مانند profile.city تبدیل کنید. آرایهها را بهصورت JSON در یک سلول نگه دارید، چون طول آنها داده است، نه مجموعهای قابلاتکا از ستونها.
- null یا فیلد غایب را بهصورت سلول خالی، مقادیر بولی و اعداد را بهصورت مقادیر JSON، رشتهها را بهصورت متن، و هر شیء یا آرایهٔ باقیمانده را بهصورت JSON فشرده بنویسید.
- وقتی محافظت از فرمول روشن است، به سلولهای رشتهای و سرستونهایی که اولین نویسهٔ معنادارشان =، +، - یا @ است یک آپاستروف پیشوند بدهید. اعداد واقعی JSON، از جمله اعداد منفی، عددی میمانند.
- هر گیومهٔ درون فیلد را دوتایی کنید و وقتی فیلد شامل جداکنندهٔ انتخابشده، گیومه یا شکست خط است آن را در گیومه بگذارید. هر ردیف را مطابق قرارداد CSV با CRLF تمام کنید.
- نشانهٔ اختیاری سهبایتی UTF-۸ را اضافه کنید، متن کامل را کدگذاری کنید و برای خروجی کاما یا نقطهویرگول .csv و برای تب .tsv ارائه دهید. در هیچ مرحلهای چیزی به جایی فرستاده نمیشود.
فرضها
- شکلهای سطح بالای پشتیبانیشده عبارتاند از یک شیء، آرایهای فقط از اشیا، یا آرایهای فقط از آرایهها. یک مقدار ابتدایی، آرایهٔ خالی یا مخلوطی از شکلهای ردیف جدول بیابهامی ندارد و رد میشود.
- ستونهای اشیا اجتماع کلیدها در همهٔ ردیفهاست، مرتبشده بر اساس اولین ظهور هر کلید. غایب و null هر دو سلول خالی CSV هستند، چون CSV مقدار null مجزایی ندارد.
- مسطح کردن فقط از میان اشیا پایین میرود. آرایهها بهصورت JSON فشرده در یک سلول میمانند؛ گسترش جایگاههای فهرست به یک ردیف غیرمعمولِ بلند اجازه میداد هزاران ستون بسازد و وانمود میکرد جایگاه در هر رکورد یک معنا دارد.
- نقطه یا بکاسلش لفظی درون یک کلید JSON پیش از بههمپیوستن بخشهای مسیر با بکاسلش escape میشود، بنابراین کلیدی به نام profile.city نمیتواند با مسیر تودرتوی profile و سپس city تداخل کند.
- محافظت از فرمول فقط به رشتههای JSON و نام ستونها اعمال میشود. عدد نوعدارِ JSON که با علامت منفی آغاز میشود دستنخورده میماند؛ همان مقدار اگر رشته باشد پیشوند میگیرد، چون صفحهگسترده نوع سلول را از متن CSV تشخیص میدهد.
- نشانهٔ UTF-۸ بهطور پیشفرض برای نسخههای قدیمی اکسل روشن است. سه بایت EF BB BF را اضافه میکند و هیچ دادهٔ ردیف یا ستونی ندارد؛ ابزارهای دیگر صفحهگسترده و پایگاه داده معمولاً آن را تحمل میکنند.
- خروجی کاما و نقطهویرگول پسوند .csv دارد. جداکنندهٔ تب از .tsv و نوع MIME text/tab-separated-values استفاده میکند، نه اینکه دادهٔ جدولی را جداشده با کاما برچسب بزند.
- ورودی به ۲۰ مگابایت، ۵۰۰٬۰۰۰ ردیف و ۵٬۰۰۰ ستون محدود است. متن رندرشده به ۶۴ میلیون نویسه محدود است تا یک گسترش نتواند حافظهٔ تب را تمام کند.
پرسشهای رایج
آیا فایل JSON پیش از تبدیل به CSV آپلود میشود؟
خیر. یک Worker در همین تب مرورگر فایل را رمزگشایی میکند، JSON را تجزیه میکند، ردیفها را میسازد و دانلود را کدگذاری میکند. آزمون مرورگری این صفحه یک فایل نمونهٔ واقعی بارگذاری میکند و اگر تا وقتی فایل حاضر است درخواستی از سایت خارج شود، شکست میخورد.
وقتی اشیای بعدی JSON کلیدهای متفاوتی داشته باشند چه میشود؟
هر کلید به ترتیب اولین ظهورش یک ستون میگیرد. رکوردهای قبلی یا بعدی که آن کلید را ندارند سلول خالی میگیرند، بنابراین مقادیر هرگز صرفاً به این دلیل که یک شیء فیلدی را جا انداخته زیر سرستون اشتباه نمیلغزند.
چرا پیش از برخی سلولهای صفحهگسترده یک آپاستروف هست؟
متنی که با =، +، - یا @ شروع میشود، وقتی CSV در نرمافزار صفحهگسترده باز شود میتواند بهعنوان فرمول تفسیر شود. محافظت از فرمول به آن رشتهها آپاستروف پیشوند میدهد تا دادهٔ خروجیگرفتهشدهٔ نامطمئن متن بماند. فقط وقتی خاموشش کنید که فرمولها عمدی و منبع مطمئن باشد.
چرا مسطح کردن یک آرایهٔ JSON را در یک سلول میگذارد؟
کلید یک شیء طرحواره است؛ طول و ترتیب یک آرایه داده است. گسترش جایگاههای آرایه به یک فهرست بلند اجازه میداد کل فایل را پهن کند و القا میکرد که عنصر صفر در هر ردیف یک معنا دارد. نگه داشتن آرایه بهصورت JSON آن را بدون ساختن چنین ادعایی حفظ میکند.
کاما، نقطهویرگول یا تب را انتخاب کنم؟
کاما پیشفرض تعاملپذیر CSV است. نقطهویرگول در زبانهای محلیای مفید است که کاما علامت اعشار است و نرمافزار صفحهگسترده انتظار جداکنندهٔ فهرست نقطهویرگول دارد. تب وقتی بهترین است که متن کاماهای زیادی دارد، و یک فایل TSV با نام صادقانه تولید میکند.
نشانهٔ UTF-۸ اکسل چیست و آیا به آن نیاز دارم؟
دنبالهٔ سهبایتی EF BB BF در ابتدای فایل است. به نسخههای قدیمیتر اکسل کمک میکند UTF-۸ را بدون پنجرهٔ درونریزی تشخیص دهند، بنابراین نامها و خطهای غیرلاتین درست باز میشوند. ابزارهای دادهٔ مدرن معمولاً به آن نیازی ندارند و کلید پیشرفته میتواند آن را حذف کند.