دليل التحقق من JSON Schema: التحقق من هياكل البيانات
كل تطبيق يتلقى بيانات من مصادر خارجية يواجه نفس المشكلة الأساسية: هل يمكنني الوثوق بهذه البيانات؟ سواء كانت أجسام طلبات API أو ملفات التكوين أو رسائل الطوابير أو استيراد البيانات، يجب التحقق من البيانات غير الموثوقة قبل دخولها إلى نظامك. يوفر JSON Schema طريقة معيارية ومستقلة عن اللغة لتعريف شكل البيانات الصالحة والتحقق من تطابق البيانات الواردة مع هذا التعريف. يغطي هذا الدليل كل شيء من كتابة أول Schema إلى أنماط متقدمة للتحقق المعقد، مع أمثلة عملية يمكنك تطبيقها فورًا.
ما هو JSON Schema؟
JSON Schema هو مستند JSON يصف هيكل وقيود مستندات JSON الأخرى. إنه مفردات تتيح لك توثيق والتحقق من بيانات JSON، موحدة من قبل IETF. يعرف JSON Schema قواعد حول الحقول التي يجب أن تكون موجودة، وأنواعها، والقيم المقبولة، وكيفية هيكلة الكائنات والمصفوفات.
فكر في JSON Schema كعقد بياناتك. مثلما يعرف Schema قاعدة البيانات الأعمدة والأنواع والقيود، يعرف JSON Schema خصائص وأنواع وقيود مستندات JSON. أي بيانات JSON تستوفي جميع القيود في Schema تسمى مثيلاً صالحًا، بينما البيانات التي تنتهك أي قيد تكون غير صالحة.
ما ليس JSON Schema
- ليس تنسيق بيانات: JSON Schema لا يعرف كيفية تسلسل البيانات أو نقلها. يصف فقط شكل البيانات الصالحة.
- ليس بديلاً عن منطق الأعمال: يتحقق التحقق من Schema من الصحة الهيكلية (الأنواع، التنسيقات، النطاقات). قواعد الأعمال المعقدة (مثل 'لا يمكن للمستخدم تحويل أكثر من رصيده') تنتمي إلى كود التطبيق.
- ليس Schema قاعدة بيانات: بينما المفهوم مشابه، يتحقق JSON Schema من مستندات JSON، وليس جداول قواعد البيانات. ومع ذلك، يمكنك الجمع بين JSON Schema وقيود قاعدة البيانات للدفاع المتعمق.
إصدارات JSON Schema
تطور JSON Schema عبر عدة مسودات، كل منها أضافت ميزات وحسنت المفردات. معرفة هذه الإصدارات تساعدك في اختيار الإصدار المناسب لمشروعك وتجنب مشكلات التوافق.
| الإصدار | URI $schema | الحالة | الميزات الرئيسية |
|---|---|---|---|
| Draft 2020-12 | https://json-schema.org/draft/2020-12/schema | الإصدار الحالي | prefixItems, dynamicRef, دعم المفردات |
| Draft 2019-09 | https://json-schema.org/draft/2019-09/schema | مستقر | unevaluatedProperties, $recursiveRef |
| Draft 7 | http://json-schema.org/draft-07/schema# | مدعوم على نطاق واسع | if/then/else, contentEncoding |
| Draft 6 | http://json-schema.org/draft-06/schema# | قديم | propertyNames, contains |
| Draft 4 | http://json-schema.org/draft-04/schema# | مهمل | أول إصدار معتمد على نطاق واسع |
كتابة أول Schema
لنبدأ بمثال بسيط: Schema لكائن مستخدم يحتوي على الاسم والبريد الإلكتروني والعمر.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User",
"description": "A user account in the system",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "The user's full name"
},
"email": {
"type": "string",
"format": "email",
"description": "The user's email address"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150,
"description": "The user's age in years"
}
},
"required": ["name", "email"],
"additionalProperties": false
}يعلن هذا الـ Schema أن المستخدم الصالح يجب أن يكون كائنًا، حيث name و email هما خاصيتان نصيتان مطلوبتان. خاصية age اختيارية، لكن إذا كانت موجودة يجب أن تكون عددًا صحيحًا بين 0 و 150. القيد additionalProperties: false يمنع أي خصائص غير معرفة في الـ Schema، مما يلتقط الأخطاء الإملائية والحقول غير المتوقعة.
مرجع الكلمات المفتاحية الأساسية
يوفر JSON Schema مفردات غنية من الكلمات المفتاحية لتعريف القيود. إليك أهم الكلمات المفتاحية منظمة حسب الفئة.
كلمات مفتاحية النوع
| الكلمة المفتاحية | الوصف | مثال |
|---|---|---|
| type | نوع البيانات المتوقع | "type": "string" أو "type": ["string", "null"] |
| enum | قائمة القيم المسموح بها | "enum": ["active", "inactive", "pending"] |
| const | يجب أن يساوي هذه القيمة بالضبط | "const": "v2" |
قيود الأرقام
| الكلمة المفتاحية | الوصف | مثال |
|---|---|---|
| minimum | القيمة الدنيا (شاملة) | "minimum": 0 |
| exclusiveMinimum | القيمة الدنيا (غير شاملة) | "exclusiveMinimum": 0 |
| maximum | القيمة القصوى (شاملة) | "maximum": 100 |
| exclusiveMaximum | القيمة القصوى (غير شاملة) | "exclusiveMaximum": 100 |
| multipleOf | يجب أن يكون مضاعفًا لهذه القيمة | "multipleOf": 0.01 |
قيود السلاسل
| الكلمة المفتاحية | الوصف | مثال |
|---|---|---|
| minLength | الحد الأدنى لطول السلسلة | "minLength": 1 |
| maxLength | الحد الأقصى لطول السلسلة | "maxLength": 255 |
| pattern | تعبير regex يجب أن تطابقه السلسلة | "pattern": "^[A-Z]{2}\d{4}$" |
| format | تنسيق دلالي (email، uri، date-time، إلخ) | "format": "email" |
قيود الكائنات
| الكلمة المفتاحية | الوصف | مثال |
|---|---|---|
| properties | Schema لكل خاصية معروفة | "properties": {"name": {"type": "string"}} |
| required | قائمة الخصائص المطلوبة | "required": ["name", "email"] |
| additionalProperties | هل يُسمح بخصائص إضافية | "additionalProperties": false |
| minProperties | الحد الأدنى لعدد الخصائص | "minProperties": 1 |
| maxProperties | الحد الأقصى لعدد الخصائص | "maxProperties": 10 |
| patternProperties | Schema للخصائص المطابقة لـ regex | "patternProperties": {"^S_": {"type": "string"}} |
قيود المصفوفات
| الكلمة المفتاحية | الوصف | مثال |
|---|---|---|
| items | Schema لجميع عناصر المصفوفة | "items": {"type": "string"} |
| prefixItems | Schema للعناصر الموضعية (Draft 2020-12) | "prefixItems": [{"type": "string"}, {"type": "number"}] |
| minItems | الحد الأدنى لعدد العناصر | "minItems": 1 |
| maxItems | الحد الأقصى لعدد العناصر | "maxItems": 100 |
| uniqueItems | يجب أن تكون جميع العناصر فريدة | "uniqueItems": true |
أنماط Schema الشائعة
غالبًا ما تتطلب Schemas الواقعية أنماطًا تتجاوز التحقق البسيط من النوع. إليك أكثر الأنماط استخدامًا.
التحقق الشرطي باستخدام if/then/else
استخدم المنطق الشرطي لتطبيق قيود مختلفة بناءً على قيم الخصائص. على سبيل المثال، كائن الدفع يحتاج إلى حقول مختلفة حسب طريقة الدفع.
{
"type": "object",
"properties": {
"method": { "enum": ["credit_card", "bank_transfer"] },
"card_number": { "type": "string" },
"routing_number": { "type": "string" }
},
"required": ["method"],
"if": {
"properties": { "method": { "const": "credit_card" } }
},
"then": {
"required": ["card_number"]
},
"else": {
"required": ["routing_number"]
}
}التركيب باستخدام allOf و anyOf و oneOf
تتيح لك كلمات التركيب دمج Schemas بطرق قوية:
- allOf: يجب أن تستوفي البيانات جميع الـ Schemas الفرعية. تستخدم لدمج قيود متعددة أو خلط أجزاء Schema قابلة لإعادة الاستخدام.
- anyOf: يجب أن تستوفي البيانات Schema فرعيًا واحدًا على الأقل. تستخدم لأنواع الاتحاد حيث تكون عدة أشكال مقبولة.
- oneOf: يجب أن تستوفي البيانات Schema فرعيًا واحدًا بالضبط. تستخدم للبدائل المتنافية.
{
"oneOf": [
{
"type": "object",
"properties": {
"type": { "const": "email" },
"address": { "type": "string", "format": "email" }
},
"required": ["type", "address"]
},
{
"type": "object",
"properties": {
"type": { "const": "phone" },
"number": { "type": "string", "pattern": "^\\+?[1-9]\\d{1,14}$" }
},
"required": ["type", "number"]
}
]
}إعادة استخدام Schema باستخدام $ref
تتيح لك كلمة $ref المرجعية استيراد وإعادة استخدام Schemas، مما يلغي التكرار ويحافظ على قابلية صيانة Schemas. يمكنك الإشارة إلى Schemas داخل نفس المستند أو في ملفات خارجية.
{
"$id": "https://example.com/schemas/order.json",
"type": "object",
"properties": {
"customer": { "$ref": "#/$defs/address" },
"shipping": { "$ref": "#/$defs/address" },
"billing": { "$ref": "#/$defs/address" },
"items": {
"type": "array",
"items": { "$ref": "#/$defs/lineItem" },
"minItems": 1
}
},
"required": ["customer", "items"],
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^\\d{5}(-\\d{4})?$" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
},
"required": ["street", "city", "zip", "country"]
},
"lineItem": {
"type": "object",
"properties": {
"product": { "type": "string" },
"quantity": { "type": "integer", "minimum": 1 },
"price": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["product", "quantity", "price"]
}
}
}الأنواع القابلة للـ null
في JSON Schema Draft 2020-12، يتم تمثيل الأنواع القابلة للـ null باستخدام مصفوفة نوع تحتوي على "null":
{
"type": ["string", "null"],
"description": "An optional display name, or null if not set"
}في المسودات الأقدم، استخدمت مواصفات OpenAPI الكلمة المفتاحية nullable: true. بالنسبة لـ JSON Schema القياسي، استخدم دائمًا نهج مصفوفة النوع.
التحقق من التنسيق
توفر كلمة format المفتاحية تحققًا دلاليًا يتجاوز فحص الهيكل. تحدد أن السلسلة يجب أن تتوافق مع تنسيق معروف. تشمل التنسيقات المدعومة الشائعة:
| التنسيق | الوصف | مثال |
|---|---|---|
| عنوان بريد إلكتروني | user@example.com | |
| uri | URI صالح | https://example.com/path |
| uri-reference | URI أو مرجع نسبي | /path/to/resource |
| date-time | تاريخ ووقت ISO 8601 | 2026-05-19T14:30:00Z |
| date | تاريخ ISO 8601 | 2026-05-19 |
| time | وقت ISO 8601 | 14:30:00Z |
| ipv4 | عنوان IPv4 | 192.168.1.1 |
| ipv6 | عنوان IPv6 | ::1 |
| uuid | معرف فريد عالمي | 550e8400-e29b-41d4-a716-446655440000 |
| hostname | اسم مضيف إنترنت | www.example.com |
التحقق البرمجي من بيانات JSON
يكون التحقق من Schema أكثر فائدة عند دمجه في كود التطبيق. إليك أمثلة باستخدام مكتبات شائعة في لغات مختلفة.
JavaScript باستخدام Ajv
Ajv هو أكثر مدقق JSON Schema استخدامًا في JavaScript. يدعم جميع إصدارات المسودات ويوفر أداءً ممتازًا من خلال ترجمة JIT للـ Schema.
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email'],
additionalProperties: false
};
const validate = ajv.compile(schema);
const valid = validate({ name: 'Alice', email: 'alice@example.com', age: 30 });
if (!valid) {
console.log(validate.errors);
// [{ keyword: 'required', params: { missingProperty: 'email' }, ... }]
}Python باستخدام jsonschema
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "email"],
"additionalProperties": False
}
try:
validate(instance={"name": "Alice", "email": "alice@example.com"}, schema=schema)
except ValidationError as e:
print(f"Validation failed: {e.message}")التحقق من بيانات API باستخدام JSON Schema
أحد أكثر تطبيقات JSON Schema قيمة هو التحقق من بيانات طلبات واستجابات API. هذا يضمن أن API الخاص بك يتلقى مدخلات منسقة جيدًا ويعيد البيانات بالتنسيق المتوقع، مما يلتقط الأخطاء مبكرًا ويوفر رسائل خطأ واضحة للعملاء.
وسيط Express.js
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true });
function validateBody(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
if (!validate(req.body)) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors
});
}
next();
};
}
app.post('/api/users',
validateBody({
type: 'object',
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
email: { type: 'string', format: 'email' },
role: { enum: ['admin', 'editor', 'viewer'] }
},
required: ['name', 'email'],
additionalProperties: false
}),
(req, res) => {
// req.body is guaranteed valid here
createUser(req.body);
}
);OpenAPI و JSON Schema
يستخدم OpenAPI (المعروف سابقًا بـ Swagger) مجموعة فرعية من JSON Schema لتعريف Schemas طلبات واستجابات API. إذا كنت تستخدم OpenAPI بالفعل، يمكنك استخراج الـ Schemas من مواصفات API واستخدامها للتحقق في وقت التشغيل. أدوات مثل openapi-schema-validator و express-openapi-validator تؤتمت هذه العملية، مما يضمن بقاء توثيق API ومنطق التحقق متزامنين دائمًا.
أفضل الممارسات
- عيّن دائمًا $schema: ضمن كلمة $schema المفتاحية للإعلان عن إصدار المسودة الذي يستخدمه Schema الخاص بك. هذا يمنع الغموض ويضمن أن المدقق يفسر Schema بشكل صحيح.
- استخدم $id كمعرف Schema: توفر كلمة $id المفتاحية معرفًا فريدًا لـ Schema الخاص بك وتعمل كـ URI أساسي لحل مراجع $ref. عيّنها دائمًا حتى للـ Schemas المحلية.
- عيّن additionalProperties: false: افتراضيًا، يسمح JSON Schema بأي خصائص إضافية في الكائنات. تعيين additionalProperties: false يلتقط الأخطاء الإملائية والحقول غير المتوقعة، مما يجعل Schema أكثر صرامة و API أكثر قابلية للتنبؤ.
- استخدم $defs للمكونات القابلة لإعادة الاستخدام: عرّف Schemas الشائعة في $defs وارجع إليها باستخدام $ref. هذا يقلل التكرار ويجعل Schemas أسهل في الصيانة.
- أضف الوصف (description): يجب أن يكون لكل خاصية و Schema حقل description. هذا يعمل كتوثيق ويساعد المطورين الآخرين في فهم غرض وقيود كل حقل.
- تحقق عند حدود النظام: طبق التحقق من Schema عند حواف نظامك: نقاط نهاية API، مستهلكي الرسائل، أنابيب استيراد البيانات، ومحمّلات التكوين. لا تتحقق من البيانات التي أنتجها كودك الخاص وتثق بها بالفعل.
- مكّن الوضع الصارم في المدقق: كوّن المدقق لرفض الكلمات المفتاحية غير المعروفة، وفرض التحقق من التنسيق، والإبلاغ عن جميع الأخطاء بدلاً من التوقف عند أول خطأ. هذا يلتقط المزيد من المشكلات في تحقق واحد.
- تحكم في إصدارات Schemas: ضمن إصدار الـ Schema في URI الخاص بـ $id (مثل https://example.com/schemas/user/v2.json). هذا يسمح لك بتطوير Schemas دون كسر المستهلكين الحاليين.
- اختبر Schemas الخاصة بك: اكتب اختبارات وحدة لـ Schemas تتضمن أمثلة صالحة وغير صالحة. هذا يضمن أن Schema ينفذ القيود التي تقصدها ويلتقط التراجعات عند تعديل الـ Schema.
- استخدم format للتحقق الدلالي: فضل format: "email" على أنماط regex المعقدة. التنسيقات أكثر قابلية للقراءة والصيانة، وتستفيد من منطق التحقق المختبر جيدًا في مكتبات المدققين.
تحتاج إلى التحقق من بيانات JSON مقابل Schema؟ جرب مدقق JSON Schema المجاني عبر الإنترنت. الصق الـ Schema والبيانات واحصل على نتائج تحقق فورية مع رسائل خطأ مفصلة.
مدقق JSON Schemaأداة تنسيق JSONالأسئلة الشائعة
ما هو JSON Schema؟
JSON Schema هو مستند JSON يصف هيكل وقيود مستندات JSON الأخرى. يتيح لك تعريف الحقول المطلوبة وأنواع البيانات المتوقعة ونطاقات القيم وأنماط السلاسل وهياكل الكائنات المتداخلة. يمكنك استخدامه للتحقق من البيانات الواردة وتوليد التوثيق وإنشاء واجهات نماذج تلقائيًا.
أي إصدار من JSON Schema يجب استخدامه؟
للمشاريع الجديدة، استخدم JSON Schema Draft 2020-12. هذا هو أحدث إصدار مستقر وتدعمه مكتبات التحقق الرئيسية مثل Ajv. إذا كنت بحاجة إلى التوافق مع أدوات قديمة، فإن Draft 7 مدعوم أيضًا على نطاق واسع. تجنب Draft 4 والإصدارات الأقدم لأنها تستخدم كلمات مفتاحية قديمة وتفتقر إلى الميزات الحديثة.
ما الفرق بين JSON Schema وواجهات TypeScript؟
توفر واجهات TypeScript فحصًا للأنواع في وقت الترجمة فقط داخل كود TypeScript. يوفر JSON Schema تحققًا في وقت التشغيل عبر لغات البرمجة، ويمكنه التحقق من البيانات من أي مصدر (طلبات API، ملفات، قواعد بيانات). استخدم TypeScript لأمان وقت التطوير، و JSON Schema للتحقق من البيانات في وقت التشغيل عند حدود النظام.
هل يمكن لـ JSON Schema التحقق من أجسام طلبات API؟
نعم، يستخدم JSON Schema على نطاق واسع للتحقق من طلبات واستجابات API. أطر العمل مثل Express (مع express-json-validator) و FastAPI و Spring Boot تدعم بشكل أصلي أو عبر وسيط التحقق من JSON Schema. التحقق من أجسام الطلبات مقابل Schema يضمن أن البيانات الواردة لها الهيكل الصحيح قبل معالجتها من قبل التطبيق.
ما هي أهم كلمات JSON Schema المفتاحية؟
أكثر الكلمات المفتاحية أهمية هي: type (نوع البيانات)، properties (حقول الكائن)، required (الحقول المطلوبة)، items (Schema عناصر المصفوفة)، minimum/maximum (حدود رقمية)، minLength/maxLength (حدود السلاسل)، pattern (regex للسلاسل)، enum (القيم المسموح بها)، و $ref (مراجع لإعادة استخدام Schemas). تغطي هذه الكلمات المفتاحية الغالبية العظمى من احتياجات التحقق.