TOML مقابل JSON مقابل YAML: أي صيغة إعداد تختار؟
إليك الخلاصة المختصرة لموضوع TOML مقابل JSON مقابل YAML: JSON هي الصيغة الافتراضية للتبادل بين الآلات والتي تحللها كل لغة برمجة، وYAML هي الصيغة الملائمة للبشر التي تشغّل Kubernetes وخطوط التكامل المستمر (CI)، وTOML هي الصيغة الصريحة ذات الأنواع المحددة المصممة لإعدادات الأدوات والتطبيقات مثل Cargo.toml وpyproject.toml. لا توجد صيغة واحدة تتفوق في كل المواقف. تعتمد صيغة ملف الإعداد المناسبة على ثلاثة أمور: مَن يحرّرها، وهل تحتاج إلى تعليقات، ومدى الصرامة المطلوبة في الأنواع.
قاعدة سريعة للتقدير. إذا كانت الآلة هي من يكتب الملف والآلة هي من يقرأه، فاختر JSON. وإذا كان شخص ما يحرّر بنية تحتية عميقة التداخل يدويًا كل يوم، فإن YAML تستحق تعقيدها. وإذا أردت إعدادًا واضحًا ومحدد الأنواع يصعب الخطأ فيه، فإن TOML هي الخيار الأكثر أمانًا. هذه الصيغ لا تتنافس؛ بل تشغل مسارات مختلفة: JSON للآلات، وYAML لعمليات التطوير والتشغيل (DevOps)، وTOML لإعدادات الأدوات. يدعم بقية هذا الدليل ذلك بأمثلة جنبًا إلى جنب، والفروق التي تسبب الأخطاء فعليًا، ومصفوفة قرار يمكنك تطبيقها على مشروعك القادم.
الإجابة في 30 ثانية
إن لم يكن لديك سوى نصف دقيقة، فهذا الجدول هو مقارنة صيغ ملفات الإعداد التي جئت من أجلها.
| JSON | YAML | TOML | |
|---|---|---|---|
| التعليقات | لا | نعم (#) | نعم (#) |
| أنواع البيانات | صريحة، بسيطة | ضمنية (تُستنتج من الشكل) | صريحة، غنية |
| تواريخ أصيلة | لا | تعتمد على الإصدار | نعم (أربعة أنواع) |
| نمط التداخل | أقواس {} | مسافات بادئة | ترويسات [section] |
| الحساسية للمسافات البادئة | لا | نعم (علامات الجدولة ممنوعة) | لا |
| سلاسل نصية متعددة الأسطر | لا (فقط \n) | نعم (| و>) | نعم (""") |
| الفواصل الزائدة | ممنوعة | غير منطبق | مسموحة في المصفوفات |
| مجموعة شاملة لـJSON | — | نعم (1.2) | لا |
| الأفضل لـ | واجهات برمجة التطبيقات، تبادل البيانات | K8s، CI، Ansible | إعدادات أدوات Rust/Python |
تنبثق ثلاثة أحكام من سطر واحد من هذا الجدول:
- اختر JSON عندما تُنتَج الملفات وتُستهلَك بواسطة البرامج: حمولات واجهات برمجة التطبيقات (API)، و
package.json، وtsconfig.json، وأي شيء يعبر حدود نظام. - اختر YAML عندما يحرّر البشر إعدادات عميقة ومتداخلة يدويًا وتكون المنظومة تتوقعها أصلًا: بيانات Kubernetes الوصفية، وGitHub Actions، وDocker Compose، ودفاتر تشغيل Ansible.
- اختر TOML عندما تريد إعدادًا واضحًا ومحدد الأنواع لأداة أو تطبيق، مسطّحًا في معظمه مع بضعة أقسام، يحرّره مساهمون بمستويات مهارة متفاوتة:
Cargo.toml، وpyproject.toml، وHugo، وNetlify.
أما لماذا تصح هذه الأحكام، فهذا حيث تختبئ الأخطاء الحقيقية، وهو ما يشرحه بقية الدليل.
الإعداد نفسه بثلاث طرق
أوضح طريقة لرؤية الفرق هي كتابة الإعداد نفسه ثلاث مرات. إليك إعداد خدمة صغير: اسم وإصدار، وزوج من الرايات في المستوى الأعلى، وقائمة ميزات، وكتلة قاعدة بيانات متداخلة.
JSON:
{
"name": "acme-api",
"version": "2.4.0",
"debug": false,
"released": "2026-07-02",
"features": ["auth", "metrics", "tracing"],
"database": {
"host": "db.internal",
"port": 5432,
"max_connections": 100
}
}
YAML:
name: acme-api
version: "2.4.0"
debug: false
released: "2026-07-02"
features:
- auth
- metrics
- tracing
database:
host: db.internal
port: 5432
max_connections: 100
TOML:
name = "acme-api"
version = "2.4.0"
debug = false
released = "2026-07-02"
features = ["auth", "metrics", "tracing"]
[database]
host = "db.internal"
port = 5432
max_connections = 100
الثلاثة جميعها تصف البيانات ذاتها. انظر إلى ما تتعثر عليه عينك. تحمل JSON أكبر قدر من علامات الترقيم: كل مفتاح محاط بعلامتَي اقتباس مزدوجتين، وكل مستوى يضيف أقواسًا معقوفة، وفاصلة زائدة واحدة شاردة تُعدّ خطأً نحويًا. تزيل YAML معظم ذلك تقريبًا، فتأتي البنية من المسافات البادئة وحدها، وهو ما يُقرأ بجمال إلى أن تتسلل علامة جدولة. تقع TOML بين الاثنتين: علامات اقتباس على السلاسل النصية فقط، وأزواج key = value، وترويسة [database] تسمّي الكتلة المتداخلة تمامًا كما كان يفعل ملف INI القديم. لاحظ أن الحقل released سلسلة نصية محاطة باقتباس في الصيغ الثلاث كي تبقى البيانات متطابقة هنا. هذا مقصود، لأن التواريخ هي بالضبط حيث تتوقف هذه الصيغ عن الاتفاق، وهو الأمر التالي الجدير بالفهم.
JSON — الصيغة الافتراضية للتبادل بين الآلات
JSON هي الصيغة التي تلجأ إليها دون تفكير، وعادةً ما تكون هذه الغريزة صائبة. كل لغة رئيسية تأتي مزودة بمحلّل، وكل واجهة برمجة تطبيقات عبر HTTP تتحدثها، وقواعدها النحوية صغيرة بما يكفي لتحفظها في ذهنك. إنها صارمة ولا لبس فيها: السلسلة النصية سلسلة نصية، و5432 رقم، وtrue قيمة منطقية، وهناك طريقة واحدة بالضبط لكتابة كلٍّ منها. هذه الصرامة هي ما يجعل JSON آمنة للإرسال بين أنظمة لم تلتقِ قط. عندما ترسل خدمة Node بيانات JSON إلى خدمة Go، يتفق الطرفان على المعنى بايتًا ببايت.
هذه الصرامة ذاتها هي سبب هيمنة JSON على أرضها. فملفات package.json وtsconfig.json وcomposer.json مكتوبة بـJSON لأن الأدوات تولّدها وتعيد كتابتها باستمرار، والإعداد الذي تكتبه الآلة يريد صيغة صارمة تناسب الآلة. أما بالنسبة إلى حمولات واجهات برمجة التطبيقات وطوابير الرسائل فلا يوجد ببساطة أي سبب لاختيار شيء آخر.
تظهر كل نقاط ضعف JSON في اللحظة التي يضطر فيها إنسان إلى تحريرها يدويًا. لا توجد تعليقات. ولا توجد فواصل زائدة، لذا فإعادة ترتيب قائمة تعني إصلاح الفواصل. ولا توجد سلاسل نصية متعددة الأسطر، بل فقط محارف الهروب \n. وكل مفتاح يحتاج إلى علامتَي اقتباس مزدوجتين. ولا يوجد نوع للتاريخ، لذا يجب أن يعيش 2026-07-02 كسلسلة نصية محاطة باقتباس ويُحلَّل بحسب العُرف. بالنسبة إلى ملف إعداد يصونه شخص، تتراكم هذه الثغرات لتصبح احتكاكًا.
مشكلة «JSON لا تدعم التعليقات»
أكثر ميزة مطلوبة في JSON هي تلك التي تعمّد Douglas Crockford تركها: التعليقات. كان تعليله أن التعليقات تُغري الناس بتهريب توجيهات تحليل إلى ملفات الإعداد، فتكسر قابلية التشغيل البيني. أيًّا كان رأيك في هذا القرار، فلا يمكنك التعليق على إعداد JSON الخالص، وهو أمر مؤلم لأي شيء يصونه البشر. الحل العملي هو مجموعة شاملة. تضيف JSON5 التعليقات، والفواصل الزائدة، والمفاتيح غير المحاطة باقتباس، وعلامات الاقتباس المفردة؛ و**JSONC** (أي JSON مع تعليقات) هي البديل الأخف الذي يستخدمه VS Code لإعداداته. كلاهما يحافظ على شكل JSON مع جعلها قابلة للتحرير. إن كنت تحتاج إلى تعليقات لكنك تريد البقاء ضمن عائلة JSON، فاقرأ دليلنا لتنسيق JSON5 وJSONC لمعرفة متى تستخدم كلًّا منهما وكيف تُبقي أدواتك سعيدة.
YAML — المعيار الملائم للبشر في عمليات التطوير والتشغيل
تُحسّن YAML من أجل الإنسان الجالس أمام لوحة المفاتيح. فهي تدعم التعليقات، ويحافظ تخطيطها القائم على المسافات البادئة على نظافة البنى العميقة التداخل، وتتيح لك المراسي (anchors) تعريف كتلة مرة واحدة وإعادة استخدامها باسم مستعار بدلًا من النسخ واللصق:
defaults: &defaults
timeout: 30
retries: 3
staging:
<<: *defaults
host: staging.internal
production:
<<: *defaults
host: prod.internal
يسمّي المرساة &defaults كتلةً، ويدمجها <<: *defaults في البيئتين معًا، بحيث يحدث أي تغيير في المهلة المشتركة في مكان واحد. لا تملك JSON ولا TOML أي شيء مماثل. هذه القابلية للقراءة هي سبب تحوّل YAML إلى اللغة المشتركة للعمليات: فبيانات Kubernetes الوصفية، وسير عمل GitHub Actions، وملفات Docker Compose، ودفاتر تشغيل Ansible، كلها مكتوبة بـYAML. عندما يكون إعدادك عميقًا بخمسة مستويات ويعدّله إنسان يوميًا، فإن قلة علامات الترقيم في YAML تُشكّل راحة حقيقية.
الثمن هو التعقيد والمفاجأة. مواصفة YAML 1.2 كبيرة، والامتثال الكامل لها نادر، لذا تختلف المحلّلات المختلفة عند الأطراف. المسافات البادئة ذات دلالة، وعلامات الجدولة ممنوعة تمامًا، ومسافة واحدة في غير محلها قد تغيّر المعنى أو تفشل في التحليل. الحدّ الأكثر حدّة هو تحديد الأنواع الضمني: تخمّن YAML نوع القيمة القياسية غير المحاطة باقتباس من شكلها، وتخطئ في التخمين بما يكفي لتكسب لقبًا خاصًا.
مشكلة النرويج في فقرة واحدة
اكتب country: NO في YAML وستمنحك محلّلات كثيرة القيمة المنطقية false، لا السلسلة النصية "NO"، لأن YAML 1.1، التي لا تزال معظم أدوات Kubernetes تتبعها، تعامل NO وYES وON وOFF وY وN كقيم منطقية. يتحول رمز دولة النرويج إلى false بصمت ودون أي خطأ. وتحديد الأنواع الضمني نفسه يحوّل 0755 إلى رقم ثُماني و1.20 إلى 1.2. الحل ممل لكنه موثوق: أحِط بعلامات الاقتباس أي سلاسل نصية قد يُساء فهمها على أنها شيء آخر. هذا الفخ مشهور بما يكفي ليستحق تحليلًا معمّقًا خاصًا به، بما في ذلك أعطال حقيقية وتاريخ YAML 1.1 مقابل 1.2، في دليلنا لمشكلة النرويج في YAML. وبالنسبة إلى هذا المقال، الخلاصة بسيطة: راحة YAML وخطرها ينبعان من الميزة نفسها.
تنتصر YAML عندما يحرّر الناس إعدادات عميقة التداخل كل يوم وتتطلبها المنظومة المحيطة أصلًا. إن كنت تكتب مخطط Helm، فأنت تكتب YAML، ولا بأس في ذلك.
TOML — إعداد صريح مبني للأدوات
صُممت TOML (اختصارًا لـ Tom’s Obvious, Minimal Language، من إنشاء Tom Preston-Werner) لتكون صيغة الإعداد التي تمنّى مستخدمو YAML لو كانت لديهم: قابلة للقراءة، لكن دون تخمين. سمتها المميزة هي الصراحة. الأنواع لا لبس فيها، فـport = 5432 عدد صحيح دائمًا وname = "acme" سلسلة نصية دائمًا، دون استنتاج قائم على الشكل تتعثر فيه. تستعير صياغة TOML ترويسة [section] من ملفات INI، مما يجعل المستوى الأعلى من الإعداد قابلًا للمسح البصري، وهي غير حساسة للمسافات البادئة، فالمسافات البيضاء لا تغيّر المعنى أبدًا. مواصفة TOML 1.0.0 صغيرة ومستقرة، وهذه ميزة: هناك أقل ما يمكن أن تخطئ في تذكّره.
القدرة البارزة في TOML هي أنواع التاريخ والوقت الأصيلة، التي لا تعالجها JSON ولا YAML الخالصة بنظافة. لديها أربعة منها: تاريخ ووقت بإزاحة تحمل منطقة زمنية (1979-05-27T07:32:00Z)، وتاريخ ووقت محلي بلا منطقة زمنية، وتاريخ محلي (1979-05-27، مجرد يوم في التقويم)، ووقت محلي (07:32:00). هذا يعني أن تاريخ النشر يبقى تاريخًا حقيقيًا بدلًا من سلسلة نصية عليك إعادة تحليلها.
ثلاث قطع من صياغة TOML تقوم بمعظم العمل. ترويسة [section] تفتح جدولًا؛ وترويسة منقّطة مثل [tool.ruff] تُعشّش جدولًا داخل آخر دون مسافات بادئة إضافية؛ وجدول مضمّن { version = "1.0", features = ["derive"] } يحزم كائنًا صغيرًا في سطر واحد. الأقسام المتكررة تستخدم ترويسة مضاعفة، أي مصفوفة الجداول:
[[servers]]
name = "alpha"
ip = "10.0.0.1"
[[servers]]
name = "beta"
ip = "10.0.0.2"
تصبح تلك الكتلة مصفوفة JSON من كائنين تحت المفتاح servers. تُقرأ جيدًا لقائمة مسطّحة، وهو بالضبط ما تحتاجه معظم إعدادات الأدوات.
نقاط الضعف حقيقية لكنها ضيقة. لا تملك TOML نوعًا للقيمة العدمية (null)، لذا فالقيمة الغائبة هي ببساطة مفتاح محذوف. التداخل العميق يصبح مطوّلًا، لأن كل مستوى من بنية متداخلة متكررة يكرّر ترويسة [[path]] كاملةً، وهو ما يصبح أكثر ضجيجًا من مكافئه في YAML. وTOML أحدث وأقل عالمية من JSON أو YAML، لذا لا تتحدثها كل أداة. تتألق TOML في الإعدادات المسطّحة في معظمها مع حفنة من الأقسام المعنونة، وهو ما يصف الغالبية الساحقة من إعدادات الأدوات.
لماذا TOML لـRust وPython؟
يواكب صعود TOML منظومتين تبنّتاها كمعيار. مدير حزم Rust، أي Cargo، يستخدم Cargo.toml لكل حزمة (crate)، لذا يقرأ كل مطوّر Rust ويكتب TOML منذ اليوم الأول. ثم تبعتها Python: قدّم PEP 518 ملف pyproject.toml للتصريح بمتطلبات البناء، ووحّد PEP 621 بيانات المشروع الوصفية (الاسم، والإصدار، والاعتماديات، وأقسام [tool.*]) في الملف نفسه، مستبدلًا بذلك تشتّت ملفات setup.py وsetup.cfg والإعدادات الخاصة بكل أداة. وإلى جانب هاتين، تعتمد Hugo وNetlify وPoetry وFoundry جميعها TOML افتراضيًا. القاسم المشترك هو إعدادات الأدوات التي يحرّرها المساهمون يدويًا والتي تستفيد من كونها واضحة بدلًا من كونها ذكية.
وجهًا لوجه — الفروق التي تؤذي فعلًا
جداول الميزات تبدو مرتبة، لكن الأخطاء التي تصادفك فعلًا ليست كذلك. هذه هي الفروق المحددة التي تسبب مشكلات حقيقية، ولكلٍّ منها مثال صغير يمكنك تمريره عبر أي محلّل.
التعليقات
لا تملك JSON أي صياغة للتعليقات على الإطلاق. تستخدم كلٌّ من TOML وYAML الرمز # حتى نهاية السطر.
# TOML: a leading comment
port = 5432 # and a trailing one
# YAML: identical comment style
port: 5432 # trailing comment
في اللحظة التي تلصق فيها // أو # داخل JSON صارمة، يفشل التحليل. هذا ليس أمرًا تجميليًا. فالإعداد الذي يصونه إنسان دون تعليقات يراكم معرفة قبلية لا تعيش إلا في رأس أحدهم.
أنواع البيانات والتواريخ
أنواع JSON صريحة لكنها شحيحة، بلا نوع للتاريخ. وأنواع TOML صريحة وغنية. أما أنواع YAML فضمنية، وكما ورد أعلاه، خاطئة أحيانًا. التواريخ هي أوضح خط فاصل. تعبّر TOML عن الأنواع الأربعة جميعها بشكل أصيل:
odt = 1979-05-27T07:32:00Z # offset date-time (has timezone)
ldt = 1979-05-27T07:32:00 # local date-time (no timezone)
ld = 1979-05-27 # local date (a calendar day)
lt = 07:32:00 # local time
حوّل تلك الـTOML إلى JSON وستصبح كل قيمة سلسلة نصية تحتفظ بمعناها: يبقى التاريخ المحلي "1979-05-27" بدلًا من أن يُنفَخ إلى طابع زمني مزيف عند منتصف الليل. محوّل TOML إلى JSON لدينا يحافظ على نوع التاريخ هذا بدقة، وهو ما تخطئ فيه كثير من المحوّلات الساذجة. أما YAML فقد تعامل 1979-05-27 كتاريخ أو لا تعامله كذلك حسب المحلّل وإصدار المخطط، وهو بالضبط الغموض الذي لا تريده في إعدادات الإنتاج.
عمق التداخل
كلما ازداد عمق تداخل إعدادك، ازداد تباعد الصيغ. خذ شجرة صغيرة على نمط Docker Compose:
services:
web:
build:
context: .
args:
NODE_ENV: production
ports:
- "8080:8080"
تعبّر YAML عن العمق بمسافات بادئة خالصة، وتبقى متراصّة. البنية نفسها في TOML تجبرك على كتابة المسار الكامل في كل ترويسة، وعلى نقل القيم القياسية قبل الجداول الفرعية:
[services.web]
ports = ["8080:8080"]
[services.web.build]
context = "."
[services.web.build.args]
NODE_ENV = "production"
تحمل JSON الشجرة في أقواس معقوفة متداخلة، وهو أمر لا لبس فيه لكنه مثقل بعلامات الترقيم. بالنسبة إلى الإعدادات الضحلة تبدو الثلاثة متشابهة؛ وبعد ثلاثة أو أربعة مستويات، تكون YAML أنحف بشكل ظاهر وTOML أكثر تكرارًا بشكل ظاهر. هذا الفرق الواحد يفسّر لماذا اختارت Kubernetes الـYAML واختارت Cargo الـTOML.
الحساسية للمسافات البادئة
وحدها YAML تهتم بالمسافات البيضاء. في JSON وTOML يمكنك وضع المسافات البادئة كيفما شئت، أو ألّا تضعها إطلاقًا، ويبقى المعنى متطابقًا. أما في YAML فالمسافة البادئة هي البنية، وعلامات الجدولة غير قانونية، لذا فإن محرّرًا يُدرج علامة جدولة أو كتلةً مُلصَقة على عمق خاطئ يغيّر المستند بصمت أو يرفض تحميله. عنصر قائمة أُزيح بمسافة واحدة زائدة قد يلتصق بالمفتاح الأب الخاطئ دون أي خطأ، وهو خطأ يثير الجنون عند رصده بالعين لأن الملف لا يزال يبدو معقولًا. إن كان مساهموك يستخدمون محرّرات وإعدادات مختلطة، فتلك ضريبة دائمة تفرضها YAML ولا يفرضها الاثنان الآخران، وهي سبب قوي لتشغيل مدقّق (linter) ضمن CI على أي إعداد YAML كبير.
السلاسل النصية متعددة الأسطر
لا تستطيع JSON أن تحمل سطرًا جديدًا حرفيًا داخل سلسلة نصية؛ بل تهربه على هيئة \n. تملك كلٌّ من YAML وTOML سلاسل نصية متعددة الأسطر حقيقية.
{ "note": "line one\nline two" }
note: |
line one
line two
note = """
line one
line two
"""
يحافظ الرمز | في YAML على الأسطر الجديدة (بينما تطوي كتلة > هذه الأسطر إلى مسافات)، ويتصرف """ في TOML تصرفًا مشابهًا، إذ يقتطع السطر الجديد الذي يلي علامات الاقتباس الافتتاحية مباشرة. بالنسبة إلى النصوص البرمجية المضمّنة، أو SQL، أو نص المساعدة، قد يحسم هذا وحده اختيار الصيغة.
الفواصل الزائدة والصرامة
JSON هي الأكثر صرامة بين الثلاث. الفاصلة الزائدة بعد آخر عنصر في المصفوفة خطأ نحوي:
# valid TOML — the trailing comma is fine
ports = [
8001,
8002,
]
الفاصلة الزائدة نفسها بعد 8002 في JSON تفشل في التحليل، ولهذا فإن إضافة سطر إلى مصفوفة JSON تعني في الغالب أيضًا إصلاح الفاصلة في السطر الذي فوقه. تسمح TOML بالفاصلة الزائدة، وتتجنب صياغة قائمة YAML القائمة على شرطة لكل سطر هذه المسألة تمامًا. الصرامة فضيلة للتبادل بين الآلات ومصدر إزعاج للتحرير اليدوي، وهي المفاضلة نفسها منظورًا إليها من الجهة الأخرى. وهذا أيضًا هو الاحتكاك الذي سعت JSON5 وJSONC إلى إزالته لصالح JSON تحديدًا.
الأعداد الصحيحة الكبيرة وسقف 2^53
تستطيع الصيغ الثلاث جميعها أن تكتب عددًا صحيحًا بـ 64 بت كنص. تبدأ المشكلة عندما تمرّ تلك القيمة عبر JavaScript، لأن أعداد JSON في المتصفح هي أعداد مضاعفة بمعيار IEEE-754 ولا يمكنها تمثيل الأعداد الصحيحة بدقة إلا حتى 2^53 − 1 (9007199254740991). معرّف Snowflake أو طابع زمني بالنانوثانية أكبر من ذلك، لذا فإن رحلة ذهاب وإياب عبر أداة قائمة على JS تقرّبه وتفسد القيمة:
snowflake = 1420070400000000000 # exact in TOML text
{ "snowflake": "1420070400000000000" }
الحل الموثوق في كل صيغة هو تخزين هذه القيم كسلاسل نصية محاطة باقتباس، بحيث لا يلمسها أي محلّل رقمي أبدًا. هذا ليس عيبًا في أي صيغة بعينها؛ بل هو قيد في بيئة التشغيل التي تجري التحويل. تحذّرك محوّلاتنا عندما يتجاوز عدد صحيح ذلك الحد بدلًا من إفساده بصمت.
كيف تختار — مصفوفة القرار والمخطط الانسيابي
عندما تقرر فعليًا أي صيغة إعداد تستخدم، امشِ عبر الأسئلة بالترتيب وتوقف عند أول «نعم» قوية.
- هل تُكتَب الملفات وتُقرأ أساسًا بواسطة البرامج، أم أن المنظومة تفرض صيغة أصلًا؟ إن كان الجواب نعم، فاستخدم JSON. حمولة واجهة برمجة التطبيقات هي JSON. الملف المجاور لـ
package.jsonهو JSON. لا تحارب الأدوات. - هل يحرّر البشر إعدادات عميقة ومتداخلة يدويًا كل يوم، ضمن مكدّس يتوقعها (Kubernetes، CI، Ansible)؟ إن كان الجواب نعم، فاستخدم YAML، وتبنَّ عُرفًا للاقتباس لتفادي مشكلة النرويج.
- هل هو إعداد أداة أو تطبيق، مسطّح في معظمه مع بضعة أقسام، يحرّره مساهمون بمستويات مهارة متفاوتة، حيث يتفوق المحدد الأنواع والواضح على المختصر؟ إن كان الجواب نعم، فاستخدم TOML.
إن تعادل جوابان، فاحسم الأمر بخريطة المحاور هذه:
| المتطلب | الأنسب | لماذا |
|---|---|---|
| تعليقات في الملف | TOML أو YAML | JSON لا تملكها |
| قيم تاريخ/وقت أصيلة | TOML | أربعة أنواع تاريخ صريحة |
| تداخل عميق جدًا | YAML | المسافات البادئة تبقى متراصّة |
| صفر مفاجآت من المسافات البيضاء | JSON أو TOML | غير حساسة للمسافات البادئة |
| مقيّد بملف منظومة | JSON | package.json، tsconfig.json |
| تحرير بشري، أقسام قليلة | TOML | أنواع صريحة، ترويسات شبيهة بـINI |
| تبادل بين آلة وآلة | JSON | عالمية، صارمة، سريعة |
| يجب ألّا يخمّن استنتاج الأنواع أبدًا | JSON أو TOML | YAML تستنتج ضمنيًا |
تنتهي معظم المشاريع إلى استخدام أكثر من واحدة. قد يحوي مستودع ما ملف package.json بصيغة JSON لا يلمسه يدويًا أبدًا، وملف pyproject.toml بصيغة TOML لأدوات Python الخاصة به، وسير عمل بصيغة YAML في .github، وملف .env للأسرار المحلية لا يتبع أيًّا من هذه القواعد النحوية إطلاقًا. هذا المزيج طبيعي، وهو المقصود: كل ملف يعيش في الصيغة التي تناسب من يحرّره. إن كانت طبقة .env جزءًا من إعدادك، فإن دليلنا لصيغة ملف .env يغطي أين تناسب إلى جانب إعداد JSON وكيفية التحويل بين الاثنين.
التحويل بين TOML وJSON وYAML
ينتهي بك الأمر إلى التحويل بين هذه الصيغ أكثر مما تتوقع. تقرأ مهمة CI ملف pyproject.toml مكتوبًا يدويًا وتحتاجه بصيغة JSON لتغذية لوحة معلومات الاعتماديات. تنقل عملية ترحيل تطبيقًا من إعداد YAML إلى TOML من أجل تحديد أنواع أكثر صرامة. تصبح مراجعة الشيفرة أسهل عندما تقارن صيغة JSON لملفين بدلًا من أصليهما الحساسين للمسافات البيضاء. لكل اتجاه مأزق يستحق المعرفة قبل أن تلصق.
من TOML إلى JSON. الخطر الرئيسي هو التواريخ. التاريخ المحلي مثل 1979-05-27 يجب أن يبقى تاريخ تقويم، لا أن يصبح طابعًا زمنيًا عند منتصف الليل بتوقيت UTC يخترع وقتًا ومنطقة زمنية. تُسقَط التعليقات أيضًا، لأن JSON لا تستطيع حملها. محوّل TOML إلى JSON يحافظ على كل نوع تاريخ بأمانة كي تبقى رحلات الذهاب والإياب بلا خسارة.
من JSON إلى TOML. TOML أكثر صرامة بشأن البنية، لذا يمكن لأمرين أن يعيقا التحويل. يجب أن يكون المستوى الأعلى كائنًا، لأن مستند TOML هو دائمًا جدول عند جذره؛ فالمصفوفة المجردة أو القيمة القياسية لا مكان لها. وTOML لا تملك قيمة عدمية، لذا تُسقَط قيمة الكائن العدمية (مع تحذير يسرد أي المفاتيح)، بينما القيمة العدمية داخل مصفوفة ليس لها تمثيل صالح في TOML على الإطلاق. محوّل JSON إلى TOML يُظهر كلتا الحالتين صراحةً بدلًا من إنتاج ناتج معطوب.
JSON وYAML، في الاتجاهين. هنا مشكلة النرويج هي ما ينبغي الانتباه إليه: قيمة NO أو 0755 غير المحاطة باقتباس قد تنقلب نوعها وهي تعبر الحدود. محوّل JSON إلى YAML ومحوّل YAML إلى JSON يتوليان الاقتباس بحيث تبقى السلسلة النصية سلسلة نصية.
بعد أي تحويل، يجدر التحقق من صحة النتيجة. تمرير الناتج عبر مُنسّق JSON يؤكد أن الـJSON سليمة التكوين ومتسقة المسافات البادئة قبل أن تودعها أو ترسلها إلى ما بعدها. ولأن ملفات الإعداد تحمل أسرارًا (رموز السجلّات، وبيانات اعتماد قواعد البيانات، ومفاتيح النشر)، فإن كل هذه الأدوات تعمل بالكامل داخل متصفحك: لا يُرفع شيء، لذا فإن ملف Cargo.toml يحمل رمز سجلّ خاص أو ملف قيم يحمل بيانات اعتماد لا يغادر جهازك أبدًا.
الأسئلة الشائعة
هل TOML أفضل من YAML؟
لا واحدة منهما أفضل على الإطلاق؛ فاختيار TOML مقابل YAML يعود إلى الشكل. TOML أصعب في ارتكاب الخطأ بفضل الأنواع الصريحة وغياب فخاخ المسافات البادئة، لذا تنتصر لإعدادات الأدوات المسطّحة في معظمها. تعبّر YAML عن التداخل العميق بشكل أكثر تراصًّا، لذا تنتصر للبنى التحتية الكبيرة المتعددة الطبقات مثل Kubernetes.
هل ينبغي أن أستخدم JSON أم YAML لملفات الإعداد؟
بالنسبة إلى الإعداد الذي يحرّره إنسان، فضّل YAML: فهي تسمح بالتعليقات وتُقرأ بنظافة، وهو ما لا تفعله JSON. وبالنسبة إلى الإعداد الذي تولّده البرامج وتستهلكه، فضّل JSON: فهي صارمة وسريعة وعالمية. الخط الفاصل هو مَن يقوم بالتحرير، إنسان أم آلة.
لماذا لا تسمح JSON بالتعليقات؟
أزال منشئ JSON، Douglas Crockford، التعليقات عمدًا. كان يخشى أن يضمّن الناس فيها توجيهات تحليل فيكسروا قابلية التشغيل البيني بين المحلّلات. إن كنت تحتاج إلى تعليقات في ملف على شكل JSON، فاستخدم JSON5 أو JSONC، اللتين تعيدانها دون تغيير البنية الأساسية.
ما هي مشكلة النرويج في YAML؟
إنها معاملة YAML 1.1 لكلمات معينة غير محاطة باقتباس كقيم منطقية، فتصبح country: NO مساوية لـfalse بدلًا من السلسلة النصية "NO". وتتصرف YES وON وOFF بالطريقة نفسها. إحاطة القيمة بالاقتباس تمنع ذلك؛ راجع الدليل المخصص المرتبط أعلاه للقصة الكاملة.
هل تدعم TOML التعليقات؟
نعم. تستخدم TOML الرمز # للتعليقات، سواء في سطرها الخاص أو خلف قيمة، تمامًا مثل YAML. لاحظ أن التعليقات تُفقَد عند تحويل TOML إلى JSON، لأن JSON لا تملك صياغة تعليقات لحملها.
هل تستطيع TOML تمثيل كل ما تستطيعه JSON؟
تقريبًا. الفجوة بين JSON وTOML صغيرة لكنها حقيقية: TOML لا تملك نوعًا للقيمة العدمية، لذا تُسقَط القيم العدمية في JSON أو تُرفَض عند التحويل، ويجب أن يكون مستند TOML جدولًا عند المستوى الأعلى، لذا لا يمكن تحويل مصفوفة JSON مجردة أو قيمة قياسية دون تغليفها تحت مفتاح أولًا.
هل YAML مجموعة شاملة لـJSON؟
منذ YAML 1.2، نعم: أي مستند JSON صالح هو أيضًا YAML صالح، لذا يستطيع محلّل YAML قراءة JSON مباشرة. إنها حقيقة مفيدة، لكن لا تعتمد عليها كحدّ أمني، لأن محلّلات YAML تضيف ميزات (مثل المراسي) لا تملكها JSON.
أي صيغة إعداد هي الأسرع في التحليل؟
JSON هي الأسرع عمومًا، بأنضج المحلّلات وأكثرها تحسينًا في كل لغة. YAML هي الأبطأ والأكثر تعقيدًا في التحليل بسبب مواصفتها الكبيرة وتحديد أنواعها الضمني. تقع TOML في المنتصف، أقرب إلى JSON في السرعة منها إلى YAML.