ليه فيه إصدارات أصلًا؟
الـ JSON Schema اتطورت على مراحل اسمها drafts. كل draft بيضيف keywords، وساعات بيغيّر معنى keyword قديم. عشان كده:
- الـ
$schemaمهم: هو اللي بيقول للـ validator يفسّر الـ keywords بأنهي قواعد. - الأدوات مش كلها ماشية مع آخر draft: في أدوات لسه على draft-07، وفي حاجات (زي OpenAPI 3.0) ماشية على نسخة معدّلة من draft قديم.
- نفس الـ schema ممكن يتفهم مختلف:
itemsفي draft-07 غيرitemsفي 2020-12.
الإصدارات باختصار
| الـ draft | الـ $schema | أهم اللي جه فيه |
|---|---|---|
| draft-04 | http://json-schema.org/draft-04/schema# | id من غير $، exclusiveMinimum boolean، definitions |
| draft-06 | http://json-schema.org/draft-06/schema# | $id، const، contains، propertyNames، examples، exclusiveMinimum رقم، وtrue/false كـ schema |
| draft-07 | http://json-schema.org/draft-07/schema# | if/then/else، readOnly/writeOnly، $comment، contentMediaType |
| 2019-09 | https://json-schema.org/draft/2019-09/schema | $defs، unevaluatedProperties، dependentRequired/dependentSchemas، $anchor، minContains، deprecated، vocabularies، وkeywords جنب $ref |
| 2020-12 | https://json-schema.org/draft/2020-12/schema | prefixItems، items اتغير معناه، $dynamicRef، والـ format اتقسم annotation وassertion |
- لاحظ الـ URL: القديمة
http://json-schema.org/draft-07/schema#بـ#في الآخر، والجديدةhttps://json-schema.org/draft/2020-12/schemaمن غيرها. - draft-05 مش موجود فعليًا: اتنشر كتعديلات بسيطة على 04 ومتعتبرش إصدار مستقل.
- بعد 2020-12: المشروع بيشتغل على إصدار ثابت جديد، بس 2020-12 هو اللي الأدوات متفقة عليه دلوقتي. راجع الـ docs.
الفروق اللي بتعض
draft-07: "definitions": {...} و"$ref": "#/definitions/x".
2019-09+: "$defs": {...} و"$ref": "#/$defs/x".
أغلب الأدوات لسه بتفهم الاتنين.
draft-07: "items": [A, B] + "additionalItems": false.
2020-12: "prefixItems": [A, B] + "items": false.
الشكل القديم في Ajv2020: data/items must be object,boolean.
draft-04: "minimum": 0, "exclusiveMinimum": true.
draft-06+: "exclusiveMinimum": 0.
القديم في Ajv2020: data/exclusiveMinimum must be number.
draft-07: dependencies بياخد array أو schema.
2019-09+: dependentRequired للـ array وdependentSchemas للـ schema.
draft-04: "id". من draft-06: "$id". لو object عندك فيه حقل اسمه id عادي، draft-04 كان بيتلخبط.
draft-07: أي keyword جنب $ref يتجاهل (حسب الـ spec).
2019-09+: بيتطبقوا مع بعض.
مين بيدعم إيه
- Ajv:
import Ajv from "ajv"للـ draft-07 (وبيدعم draft-06 لو ضفت الـ meta-schema بتاعه).ajv/dist/2019.jsللـ 2019-09.ajv/dist/2020.jsللـ 2020-12. وdraft-04 محتاج package منفصلة اسمهاajv-draft-04. - Fastify: بيستخدم Ajv 8 بـ draft-07 by default. جرّبنا
prefixItemsفي route schema ورمىstrict mode: unknown keyword: "prefixItems". تقدر تغيّر الـ Ajv instance بتاعه، راجع الـ docs. - OpenAPI 3.0: نسخة معدّلة من draft-04/05، فيها
nullableومفيهاشconstولاtypearray. OpenAPI 3.1: متوافقة مع 2020-12 بالكامل (فصل ١١). - Zod 4:
z.toJSONSchemaبيطلّع 2020-12 by default، ومعاهtarget: "draft-7"و"draft-4"و"openapi-3.0". - ts-json-schema-generator: بيطلّع draft-07 بـ
definitions(اتجرّبت، فصل ١٠). - Python
jsonschema: بيدعم من draft-03 لحد 2020-12، وبتختار الـ class زيDraft202012Validator. - MongoDB
$jsonSchema: draft-04 بتصرف، ومش بيدعم كل الـ keywords (فصل ١١).
تختار أنهي draft؟
- مشروع جديد ومفيش قيود: 2020-12. ده اللي OpenAPI 3.1 وأغلب الأدوات الجديدة ماشية عليه.
- الأداة بتدعم draft-07 بس: (زي Fastify by default أو أدوات قديمة) اكتب draft-07 ومتستخدمش
prefixItemsولاunevaluatedPropertiesولا$defs. - OpenAPI 3.0 لسه: اكتب الـ subset بتاعها (
nullable،example، مفيشtypearray). - عندك schemas قديمة: فيه أدوات بتعمل migration أوتوماتيك بين الـ drafts. راجع الـ docs، وشغّل الـ tests بعدها.
خلّصت الفصل لما
١) نقلت schema من draft-07 لـ Ajv2020 وفيها items: [A, B]. إيه اللي هيحصل؟
schema is invalid: data/items must be object,boolean. حوّلها لـ prefixItems: [A, B] وitems: false.٢) Fastify رفض unevaluatedProperties. ليه؟
٣) OpenAPI 3.1 ولا 3.0 أقرب للـ JSON Schema؟
nullable.