ToolHub
View All Posts

دليل التحقق من 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

تطور JSON Schema عبر عدة مسودات، كل منها أضافت ميزات وحسنت المفردات. معرفة هذه الإصدارات تساعدك في اختيار الإصدار المناسب لمشروعك وتجنب مشكلات التوافق.

الإصدارURI $schemaالحالةالميزات الرئيسية
Draft 2020-12https://json-schema.org/draft/2020-12/schemaالإصدار الحاليprefixItems, dynamicRef, دعم المفردات
Draft 2019-09https://json-schema.org/draft/2019-09/schemaمستقرunevaluatedProperties, $recursiveRef
Draft 7http://json-schema.org/draft-07/schema#مدعوم على نطاق واسعif/then/else, contentEncoding
Draft 6http://json-schema.org/draft-06/schema#قديمpropertyNames, contains
Draft 4http://json-schema.org/draft-04/schema#مهملأول إصدار معتمد على نطاق واسع
توصية: استخدم Draft 2020-12 للمشاريع الجديدة. إنه أحدث إصدار مستقر مع معظم الميزات، وتدعمه مكتبات التحقق الرئيسية. إذا كنت بحاجة إلى أقصى توافق مع الأدوات الموجودة، فإن Draft 7 هو خيار آمن. تجنب Draft 4 والإصدارات الأقدم.

كتابة أول 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"

قيود الكائنات

الكلمة المفتاحيةالوصفمثال
propertiesSchema لكل خاصية معروفة"properties": {"name": {"type": "string"}}
requiredقائمة الخصائص المطلوبة"required": ["name", "email"]
additionalPropertiesهل يُسمح بخصائص إضافية"additionalProperties": false
minPropertiesالحد الأدنى لعدد الخصائص"minProperties": 1
maxPropertiesالحد الأقصى لعدد الخصائص"maxProperties": 10
patternPropertiesSchema للخصائص المطابقة لـ regex"patternProperties": {"^S_": {"type": "string"}}

قيود المصفوفات

الكلمة المفتاحيةالوصفمثال
itemsSchema لجميع عناصر المصفوفة"items": {"type": "string"}
prefixItemsSchema للعناصر الموضعية (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 بطرق قوية:

{
    "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 المفتاحية تحققًا دلاليًا يتجاوز فحص الهيكل. تحدد أن السلسلة يجب أن تتوافق مع تنسيق معروف. تشمل التنسيقات المدعومة الشائعة:

التنسيقالوصفمثال
emailعنوان بريد إلكترونيuser@example.com
uriURI صالحhttps://example.com/path
uri-referenceURI أو مرجع نسبي/path/to/resource
date-timeتاريخ ووقت ISO 86012026-05-19T14:30:00Z
dateتاريخ ISO 86012026-05-19
timeوقت ISO 860114:30:00Z
ipv4عنوان IPv4192.168.1.1
ipv6عنوان IPv6::1
uuidمعرف فريد عالمي550e8400-e29b-41d4-a716-446655440000
hostnameاسم مضيف إنترنتwww.example.com
ملاحظة مهمة: افتراضيًا، كلمة format المفتاحية هي توثيق وليست قيدًا. قد يتجاهلها المدقق ما لم تمكّن التحقق من التنسيق صراحةً. في Ajv، مرر { strict: true } أو { validateFormats: true } لفرض فحوصات التنسيق. تحقق دائمًا من أن مدققك يفرض قيود التنسيق.

التحقق البرمجي من بيانات 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 ومنطق التحقق متزامنين دائمًا.

أفضل الممارسات

تحتاج إلى التحقق من بيانات 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). تغطي هذه الكلمات المفتاحية الغالبية العظمى من احتياجات التحقق.