تبدیل JSON به YAML در خط فرمان: چهار تله پشت یک دستور yq
جمعبندی: رایجترین دستوری که در آموزشها تکرار میشود، yq -P input.json > output.yaml، در yq v4 همچنان JSON خروجی میدهد. این مقاله yq v4.44.6، PyYAML 6.0.3 و js-yaml را روی نمونهای 2.39 MB اندازه میگیرد، توضیح میدهد چرا پسوند ورودی قالب خروجی را تعیین میکند و دستور صحیح تبدیل دستهای، گیومهگذاری، تورفتگی و دقت اعداد صحیح بزرگ را میدهد.

جمع بندی: yq -P input.json > output.yaml — پرتکرارترین دستوری که از آموزشها کپی میشود — در yq v4 همچنان JSON تولید میکند. برای گرفتن YAML باید صریحاً -o=yaml (یا -oy) بدهید. -P کوتاهشده --prettyPrint است: تورفتگی و سبک بلوکی را کنترل میکند، نه قالب خروجی را.
تبدیل JSON به YAML هیچوقت عوض کردن پسوند یک فایل نبوده است. هزینه واقعی در چهار جا پنهان است: پسوند ورودی قالب خروجی را تعیین میکند، قواعد گیومه بیصدا رشتههایتان را بازنویسی میکنند، تورفتگی دنبالهها بر ابزارهای پایین دست اثر میگذارد، و یک عدد صحیح بزرگ که از yq بگذرد برای همیشه دقتش را از دست میدهد.
۱. نخست همان دستور معروف را اجرا کنید
روی یک ماشین تمیز با yq v4.44.6 نصب شده، یک ورودی حداقلی بسازید:
printf '{"a":1,"b":{"c":2}}' > s.json
yq -P '.' s.json
آنچه برمیگردد YAML نیست، بلکه JSON با تورفتگی است:
{
"a": 1,
"b": {
"c": 2
}
}
اگر طبق آموزش خروجی را به output.yaml هدایت کنید، فایلی با پسوند .yaml و محتوای JSON میگیرید. هر تجزیه کننده YAML 1.2 آن را بیرنج میخواند (JSON زیرمجموعه YAML 1.2 است؛ استدلال کامل این رابطه شمول در مرزهای تبدیل JSON، YAML و XML آمده است)، پس فعلاً خطایی رخ نمیدهد. خطا روزی رخ میدهد که کسی کامنت یا لنگر اضافه کند، یا yamllint در CI شروع کند به بیرون ریختن دیواری از truthy value should be one of.
این خطا در تیمهایی که خط لوله استقرار دارند به شکلی خاص پنهان میماند: فایل در یک job ساخته میشود، ماهها در مخازن بالا میرود و همه چون پسوندش .yaml است فرض میکنند YAML است. زنگ خطر فقط وقتی به صدا در میآید که yamllint به خط لوله اضافه شود، یا همکاری بخواهد با # توضیحی بنویسد و تجزیه کننده از نحوی شکایت کند که در JSON اصلاً وجود ندارد. آنوقت دهها artifact با قالب اشتباه ساخته شدهاند و باید همگی دوباره تولید شوند.
دستوری که واقعاً YAML میدهد، قالب خروجی را نام میبرد:
yq -o=yaml '.' s.json
# a: 1
# b:
# c: 2
۲. چرا: پسوند قالب خروجی را تعیین میکند
قاعده yq v4 این است: «قالب ورودی، قالب خروجی را تعیین میکند». قالب را از پسوند فایل ورودی حدس میزند و بدون -o همان حدس را دوباره به کار میبرد. ورودی .json → خروجی JSON. ورودی .yaml → خروجی YAML. خواندن از stdin بدون پسوند، پیشفرض YAML است.
چهار دستور روی همان ورودی، اندازهگیری شده:
| دستور | منبع ورودی | قالب واقعی خروجی | نتیجه |
|---|---|---|---|
yq -P '.' s.json |
فایل s.json |
JSON (تورفتهدار) | با هدایت به .yaml تله است |
yq -o=yaml '.' s.json |
فایل s.json |
YAML (سبک بلوکی) | درست |
yq -P -o=yaml '.' s.json |
فایل s.json |
YAML (سبک بلوکی) | درست، -P اینجا زائد است |
cat s.json | yq -P '.' |
stdin، بید پسوند | YAML (سبک بلوکی) | درست، چون پیشفرض yaml است |
ردیف سوم نکتهای مهم دارد: وقتی -o=yaml هست، -P همیشه لازم نیست، اما بیزیان هم نیست: به زمانهای بخش ششم نگاه کنید. ردیف چهارم توضیح میدهد چرا «کپی کردم و کار کرد»: خیلیها داده را از طریق pipe به yq میدهند و دقیقاً همان شاخه پسوند را دور میزنند.
تضاد با jq را هم باید برجسته کرد: jq صرفنظر از پسوند فایل همیشه JSON پس میدهد. کسی که از jq میآید عادت دارد ابزار «خودش بداند» چه قالبی میخواهد، و به همین دلیل به -P شک نمیکند. از سوی دیگر، کسی که با cat فایل | yq داده میدهد اصلاً مشکل را نمیبیند، چون در آن مسیر yq از قبل YAML را فرض میگیرد. همین دو مسیر است که باعث میشود این تله در آموزشهای فراوانی زنده بماند: هر خواننده یک گونه را امتحان میکند، هر دو «کار میکنند»، ولی فقط یکی به دلیل درستی کار میکند.
۳. تبدیل دستهای: سه دستور shell
تبدیل یک فایل فقط نقطه شروع است. تقریباً هر دلیل واقعی برای انجام این کار در خط فرمان، دستهای است: همه فایلهای پیکربندی یک پوشه، همه عکسهای گرفته شده از API، یکجا.
حلقه bash / zsh (خواناترین، برای یک پوشه):
for f in configs/*.json; do
yq -o=yaml '.' "$f" > "${f%.json}.yaml"
done
find بازگشتی (وقتی زیرپوشهها هم مهماند):
find . -name '*.json' -exec sh -c 'yq -o=yaml "." "$1" > "${1%.json}.yaml"' _ {} \;
PowerShell (روی CI ویندوزی):
Get-ChildItem *.json | ForEach-Object { yq -o=yaml '.' $_.FullName > ($_.BaseName + '.yaml') }
هر سه یک پیشنیاز سخت مشترک دارند: نخست JSON مبدأ را اعتبارسنجی کنید. مبدل، اعتبارسنج نیست: در برابر خطای نحوی، بسیاری از مبدلها فقط یک موقعیت مبهم میدهند، نه جزئیات سطربهسطری که یک اعتبارسنج تحویل میدهد. افزودن یک نگهبان داخل حلقه تقریباً هیچ هزینهای ندارد:
for f in configs/*.json; do
jq empty "$f" || { echo "invalid: $f"; continue; }
yq -o=yaml '.' "$f" > "${f%.json}.yaml"
done
jq empty بدون چاپ تجزیه میکند و روی JSON نامعتبر با کد خروج ناصفر خارج میشود. همراه set -euo pipefail، خط لوله روی نخستین فایل خراب میایستد، نه اینکه انبوهی خروجی نیمه کاره بسازد. اعتبارسنجهای مبتنی بر schema معمولاً مسیر دقیق فیلد را با instancePath نشان میدهند؛ مبدلها بهندرت چنین دقتی دارند و به همین دلیل بررسی پیشین تجمل نیست، بلکه تور ایمنی است.
دو ریزهنکته که در محیط واقعی بیشترین دردسر را میسازند. نخست گیومه دور "$f" است: بدون آن، نام فایل دارای فاصله مسیر را میشکند و حلقه در جای اشتباهی مینویسد. دوم ${f%.json}.yaml است که پسوند را از راست میبُرد: اگر فایلها config.prod.json نام دارند، نتیجه config.prod.yaml میشود که دقیقاً مطلوب است، ولی پیش از اجرا روی صدها فایل بهتر است یکبار امتحانش کنید.
۴. چهار پارامتر خروجی، چهار وظیفه جدا
فهرست پارامترهای yq بلند است، اما در مسیر JSON به YAML فقط چهارتایشان مهماند:
| پارامتر | چه میکند | چه وقت باید نوشته شود |
|---|---|---|
-o=yaml / -oy |
قالب خروجی را YAML میکند | هرگاه ورودی فایل .json است |
-P / --prettyPrint |
سبک بلوکی را تحمیل و تورفتگی را یکدست میکند | خواندن از stdin، یا وقتی تورفتگی دنبالهها مهم است |
-I=n |
پهنای تورفتگی، پیشفرض 2 | مصرفکننده 4 فاصله میخواهد (برخی راهنماهای سبک Ansible) |
--split-exp |
عناصر آرایه را به سندهای جدا میشکافد | ساختن مانیفستهای چندمنبعهای Kubernetes |
مورد چند سند جداگانه توضیح میخواهد. مانیفستهای Kubernetes بهطور قراردادی منابع را با --- جدا میکنند. ساختنشان از یک آرایه JSON:
yq -P -o=yaml '.[] | splitDoc' --split-exp 'true' kubernetes-list.json
بدون --split-exp یک دنباله YAML میگیرید؛ با آن، هر عنصر آرایه به سندی مستقل با جداکننده --- تبدیل میشود. kubectl apply هر دو را میپذیرد، ولی خوانایی diff یک مرتبه بزرگتر فرق میکند: در بازبینی کد، یک آرایه غولپیکر آدم را وادار به شمردن آکولادها میکند، حال آنکه سندهای جدا هر منبع را کامل نشان میدهند.
پارامتر -I=n از همه بیشتر فراموش میشود. yamllint و بخش بزرگی از playbookهای Ansible تورفتگی مشخصی را طلب میکنند؛ اگر YAML را با 2 فاصله بسازید و مخزن 4 فاصله بخواهد، فایل معتبر است ولی lint همان commit نخست ردش میکند. ثابت کردن -I=4 در اسکریپت تبدیل جلوی diff پر سر و صدایی را میگیرد که در آن تکتک خطها فقط به خاطر تورفتگی تغییر کردهاند.
۵. گیومه: شش شکل رشته که حتماً باید گیومه بخورند
استنتاج نوع در YAML ضمنی است. رشتهای که شبیه عدد یا بولین باشد، اگر گیومه نخورد به همان نوع تجزیه میشود. این خطر تئوری نیست: روی yq v4.44.6 اندازهگیری شد و هر شش مقدار زیر خودبهخود گیومه گرفتند، یعنی تجزیه کننده واقعاً آنها را اشتباه میخواند:
printf '{"version":"1.0","enabled":"true","port":"8080","empty":"","colon":"host: value","hash":"v # c","unicode":"端口 8080","ts":"2026-11-03"}' | yq -P -o=yaml '.'
version: "1.0"
enabled: "true"
port: "8080"
empty: ""
colon: 'host: value'
hash: 'v # c'
unicode: 端口 8080
ts: "2026-11-03"
پیامدها، یکییکی:
| مقدار اصلی (رشته JSON) | بی گیومه خوانده میشود به | اثر واقعی |
|---|---|---|
"1.0" |
اعشاری 1.0 |
شماره نسخه به عدد اعشاری بدل میشود؛ 1.10 به 1.1 فرو میریزد |
"true" |
بولین true |
منطق شرط برمیگردد یا نوعها ناهمخوان میشوند |
"8080" |
عدد صحیح 8080 |
نوع پورت عوض میشود و مقایسه رشتهای شکست میخورد |
"" |
null |
رشته خالی ناپدید میشود و مصرفکننده None میگیرد |
"host: value" |
خطای تجزیه یا نگاشت تودرتو | بعد از دونقطه حتماً باید فاصله باشد |
"2026-11-03" |
شیء تاریخ | به datetime.date سریال میشود، نه به رشته |
مورد آخر موذیترین است. در JSON تاریخ فقط یک رشته است؛ پس از تبدیل به تاریخ YAML بدل میشود و بسیاری از پیادهمسازیها هنگام برگشت آن را بهصورت شیء تاریخ سریال میکنند نه رشته اصلی، و سازگاری رفتوبرگشت میشکند. هم PyYAML و هم yq اینجا گیومه میگذارند، که در واقع پذیرفتن واقعیبودن خطر است.
همچنین دقت کنید unicode: 端口 8080 بدون گیومه آمده است: متن چینی در YAML امن است. نگرانی شما باید ترتیب کلیدها و دقت باشد که در ادامه میآیند.
در پیکربندیهایی که تیمهای فارسیزبان مینویسند یک مورد اضافه هم هست که در جدول نیامده و شایسته مراقبت است: مقدارهای بله و خیر، تاریخهای شمسی، و کدهایی با صفر آغازین مانند کد پستی 0150 یا کد ملی. با یک تجزیه کننده YAML 1.1 — که هنوز در کتابخانههای قدیمی هست — رشته no به بولین false بدل میشود، یعنی فیلدی مثل فعال: no بیآنکه کسی کد را دست بزند معنایش عوض میشود. پادزهر همان است که همیشه بود: هر مقداری را که «شبیه چیز دیگری» است گیومه بگذارید و به حدس مبدل اعتماد نکنید. کدهای دارای صفر پیشین هم از همین دستهاند: بی گیومه به عدد تبدیل میشوند و صفر ناپدید میگردد.
۶. معادلهای Python و Node، همراه زمانهای اندازهگیریشده
همهجا نمیتوان yq نصب کرد: ماشینهای آفلاین، ایمیجهای CI بسته، ویندوز بدون مدیر بسته. معادلهای Python و Node وجود دارند و هرکدام پیشفرضهای خودشان را برای گاز گرفتن آماده کردهاند. برای مقایسه سناریوبهسناریوی هر سه مسیر به انتخاب ابزارهای خط فرمان و ویرایشگر JSON نگاه کنید؛ این مقاله فقط روی جهت JSON → YAML متمرکز است.
Python + PyYAML (سه آرگومان، هیچکدام اختیاری نیست):
import json, yaml
with open("config.json", encoding="utf-8") as f:
data = json.load(f)
with open("config.yaml", "w", encoding="utf-8") as f:
yaml.safe_dump(
data, f,
default_flow_style=False, # block style, not {a: 1, b: 2}
allow_unicode=True, # keep CJK as-is, not \u7AEF\u53E3
sort_keys=False, # preserve the original key order
)
پیشفرض این سه False / False / True است، یعنی PyYAML همانطور که نصب میشود کلیدها را بهترتیب الفبا مرتب میکند و متن چینی را به \uXXXX فرار میدهد. اندازهگیری همان ورودی با پیشفرضها:
apiVersion: v1
data:
LOG_LEVEL: info
colon: 'host: value'
unicode: "\u7AEF\u53E3 8080"
kind: ConfigMap
metadata:
labels:
app: web
name: app-config
دقت کنید kind حالا بعد از apiVersion و قبل از metadata قرار گرفته است. قرارداد Kubernetes میگوید apiVersion باید پیش از kind بیاید؛ بههم ریختن ترتیب تجزیه را خراب نمیکند، ولی بازبینی را عذابآور میکند: کسی که مانیفستی را مرور میکند انتظار ترتیبی آشنا دارد و diffای که همه کلیدها را جابهجا میکند خیلی بزرگتر از آنچه هست به نظر میرسد.
Node + js-yaml:
const fs = require("fs");
const yaml = require("js-yaml");
const data = JSON.parse(fs.readFileSync("config.json", "utf8"));
fs.writeFileSync(
"config.yaml",
yaml.dump(data, { lineWidth: -1, noRefs: true, sortKeys: false })
);
lineWidth: -1 تا کردن خطوط را خاموش میکند (وگرنه URLهای بلند از وسط میشکنند) و noRefs: true جلوی ساختن لنگر و نام مستعار را میگیرد؛ وقتی مصرفکننده kubectl یا ابزاری است که آنها را حل نمیکند، این گزینه الزامی است.
زمانهای اندازهگیریشده (نمونه: JSONـی 2.39 MB، 12000 رکورد، هرکدام با یک object تودرتو و دو آرایه؛ ماشین همان sandbox این کار است):
| پیادهمسازی | زمان تبدیل | زمان تجزیه معکوس | رفتوبرگشت |
|---|---|---|---|
yq -o=yaml v4.44.6 |
0.45 s | 0.45 s | یکسان |
yq -P -o=yaml v4.44.6 |
4.16 s | — | یکسان |
| Node js-yaml 4.x | 0.23 s | 0.11 s | یکسان |
| Python PyYAML 6.0.3 | 3.26 s | 8.01 s | یکسان |
دو نتیجه خلاف شهود. نخست، اضافه کردن -P حدود 9 برابر yq را کند میکند (0.45 s → 4.16 s) در حالی که در این نمونه خروجی بایتبهبایت یکسان است (2,326,895 بایت در هر دو): -P یک پیمایش کامل چیدمان دوباره انجام میدهد و این هزینه موقع تبدیل صدها فایل در یک job جمع میشود. دوم، تجزیه معکوس PyYAML (8.01 s) بیش از دو برابر دامپ مستقیمش (3.26 s) طول میکشد، پس اگر خط لولهای مدام YAML را پس میخواند Python انتخاب خوبی نیست.
یک نکته دیگر: 2.39 MB JSON به 2.33 MB YAML بلوکی تبدیل شد، یعنی حدود 3% کوچکتر. باور رایج که «YAML همیشه از JSON بزرگتر است» درست نیست: در تودرتویی عمیق، گیومهها، کاماها و آکولادهای JSON ممکن است از فضای خالی تورفتگی YAML سنگینتر شوند. در عمل انتخاب مسیر را معمولاً محیط دیکته میکند نه جدول زمانها: اگر runner از پیش Node دارد، js-yaml سریعترین گزینه است و نیازی به دانلود باینری نیست؛ اگر تیم آفلاین است و فقط Python نصب شده، PyYAML تنها راه موجود است و باید هزینه بازخوانیش را پذیرفت.
۷. سه چیزی که برگشتنی نیستند
بخشهای قبل درباره درست تبدیل کردن بودند؛ این بخش درباره چیزهایی است که گم میشوند. ورودیای ساخته شده برای همین منظور، اندازهگیری شده:
printf '{"order_id":12345678901234567890,"zip":"0150","ts":"2026-11-03","f":1.0e6}' > t.json
yq -o=yaml '.' t.json
خروجی yq:
order_id: 1.2345678901234567e+19
zip: "0150"
ts: "2026-11-03"
f: 1000000
و برگشت به JSON: {"order_id":12345678901234567000,"zip":"0150","ts":"2026-11-03","f":1000000}.
شماره سفارش 20 رقمی 12345678901234567890 به 12345678901234567000 تبدیل شد: سه رقم آخر صفر شد، بیهیچ هشداری. yq از مسیر float64 زبان Go تجزیه میکند؛ اعداد صحیح بالاتر از 2^53 دقیقاً قابل نمایش نیستند، پس به نماد علمی پناه میبرد و تا وقتی برمیگردانید مقدار اصلی رفته است.
همان ورودی به PyYAML:
order_id: 12345678901234567890
zip: '0150'
ts: '2026-11-03'
f: 1000000.0
اعداد صحیح Python دقت دلخواه دارند، پس هر 20 رقم زنده میماند و رفتوبرگشت دستنخورده است. اگر دادههایتان شماره سفارش، شناسه snowflake یا کد ملی دارد، از yq استفاده نکنید: Python به کار ببرید یا همان اول فیلد را رشته کنید. سازوکار کامل این دسته خطاها در چرا اعداد صحیح بزرگ در JSON دقت میبازند توضیح داده شده است.
دومین تلفات، تمایز float و int است: 1.0e6 در خروجی yq به 1000000 بدل میشود، حالآنکه PyYAML 1000000.0 را نگه میدارد. سومی ترتیب کلیدهاست: PyYAML پیشفرض مرتب میکند، yq و js-yaml پیشفرض نگه میدارند، که در تیمهای چندزبانه منبع پنهان اختلاف است.
برای فروشگاههای اینترنتی و درگاههای پرداخت خواندن این بخش ناخوشایندتر هم هست: شناسه سفارش یا تراکنش 20 رقمی در diff به چشم نمیآید چون تفاوت فقط سه صفر آخر است و فایل همچنان YAML معتبر است. تنها دفاع قابل اتکا، آزمون رفتوبرگشتی است که JSON اصلی را فیلدبهفیلد با نتیجه JSON → YAML → JSON مقایسه کند و با عوض شدن حتی یک رقم شکست بخورد. مقایسه تنها تعداد بایت یا تعداد فیلد کافی نیست: اینجا هر دو فایل دقیقاً هم اندازهاند.
۸. در CI فقط تبدیل نکنید: اعتبارسنجی ← تبدیل ← lint
تبدیل را تنها گام دانستن، رایجترین نقص خط لوله است. کد خروج صفر یعنی «JSON ورودی تجزیه شد»، نه «خروجی درست است» و نه «خروجی نیاز مصرفکننده را برآورده میکند». شکل درست سه مرحلهای:
#!/usr/bin/env bash
set -euo pipefail
# 1. Validate the source: syntax layer
jq empty deployment.json
# 2. Convert: name the output format explicitly
yq -o=yaml '.' deployment.json > deployment.yaml
# 3. Validate the artifact: parseable YAML, and lint-clean
yq -o=json -I=0 '.' deployment.yaml > /dev/null
yamllint deployment.yaml
آن yq -o=json ... > /dev/null در گام ۳ بهظاهر زائد است و سودمندترین خط بلوک است: artifact را وادار میکند دوباره تجزیه شود. خطاهای تورفتگی، شکست در حل لنگرها و نوعهای بازنویسی شده همانجا رو میشوند. اگر ردش کنید، مشکل تا kubectl apply یا تا لحظه بالا آمدن برنامه صبر میکند، یعنی تا وقتی که دیگر مستقر شده است.
اگر خروجی پیکربندیی است که آدمها نگهداری میکنند (values هلم، docker-compose، workflowهای GitHub Actions)، سه چیز دیگر را هم تأیید کنید: ترتیب کلیدها بههم نخورده، اعداد طویل رقمی از دست ندادهاند، و کامنتها همچنان باید دستی اضافه شوند. JSON کامنت ندارد، پس هر توضیحی باید بعد از تبدیل نوشته شود؛ هیچ مبدلی آنها را برایتان نمیسازد.
در یک workflow از GitHub Actions این الگو بی دردسر جا میگیرد: job اعتبارسنجی روی runner تمیز اجرا میشود، jq و yamllint در همان گام نصب میشوند، و اسکریپت فقط وقتی artifact را منتشر میکند که هر سه مرحله گذشته باشند. ارزشش را دارد که نسخه ابزارها — از جمله نسخه yq — را در workflow قفل کنید، چون رفتاری که در بخش دوم توضیح داده شد متعلق به yq v4 است و لزوماً متعلق به نسخهای نیست که runner سال آینده بهطور پیشفرض نصب کند.
پرسشهای متداول
yq -P یا -o=yaml؟ بالاخره کدام را بنویسم؟
-o=yaml تعیین میکند خروجی هست YAML یا نه؛ -P تعیین میکند YAML چگونه دیده شود. با ورودی .json، -o=yaml الزامی است و -P فقط وقتی لازم است که سبک بلوکی یا تورفتگی دنبالهها را بخواهید. هنگام خواندن از stdin بدون پسوند، yq پیشفرض YAML میدهد، پس -P بهتنهایی کافی است.
آیا YAML تبدیل شده را میتوان مستقیم به Kubernetes داد؟
از نظر نحوی بله، با سه شرط: کلیدهایی با قرارداد ترتیب مثل apiVersion مرتب نشده باشند (PyYAML پیشفرض مرتب میکند؛ sort_keys=False بگذارید)، لنگر و نام مستعار ساخته نشده باشد (js-yaml؛ noRefs: true)، و اعداد طویل رقمهایشان را نگه داشته باشند. برای مانیفستهای چندمنبعهای، با --split-exp به سندهای جدا شده با --- بشکافید.
چرا خروجی من یک خط {a: 1, b: 2} است، نه تورفتهدار؟
این سبک flow است. YAML معتبر است، ولی اصل تبدیل را بیه اثر میکند. با -P سبک بلوکی را تحمیل کنید؛ با PyYAML، default_flow_style=False را تأیید کنید (از PyYAML 5.1 پیشفرضش False شده و نسخههای قدیمیتر باید صریح نوشته شوند).
شماره سفارش 20 رقمیام آخرین رقمها را از دست داد. میشود برگرداند؟
نه، فقط میشود جلویش را گرفت. yq با float64 تجزیه میکند، پس اعداد صحیح بالاتر از 2^53 ذاتاً دقت میبازند. یا به Python بروید (اعداد صحیح با دقت دلخواه؛ بیتلفات تأیید شده) یا اعداد طویل را در JSON بهصورت رشته ذخیره کنید، که مشکل مشابه JSON.parse در سمت JavaScript را هم حل میکند.
ابزار آنلاین یا خط فرمان؟
برای پیکربندیهای حاوی اسرار و عکسهای API دارای token، از خط فرمان یا ابزاری کاملاً سمت کاربر استفاده کنید؛ هرگز آپلود نکنید. برای کارهای یکباره و کوچک که تأیید چشمی میخواهید، ابزار آنلاین سریعتر است؛ صفحه /convert/yaml همین سایت تماماً در مرورگر اجرا میشود و داده از ماشینتان بیرون نمیرود. برای هر چیز دستهای، تکرارپذیر یا وابسته به CI، خط فرمان به کار ببرید و گامهای اعتبارسنجی را همانجا درون اسکریپت بنویسید.