يمكن أن يحتوي ملف JSON على أقواس وفواصل صحيحة تمامًا، ومع ذلك يتسبب في خلل داخل البرنامج لأن حقلًا مطلوبًا غير موجود، أو لأن quantity نص بدل عدد، أو لأن price سالب. فكيف تتحقق من صحة بيانات JSON في بايثون قبل استخدامها في تطبيقك؟
في هذا الدرس من سلسلة بايثون بعد الأساسيات 12 سنستخدم مكتبة jsonschema لبناء قواعد للتحقق من بيانات طلب متجر، وفحص الحقول المطلوبة والأنواع والقيم والقوائم المتداخلة، ثم إنتاج تقرير بكل الأخطاء ومساراتها. سنشغل الأكواد على ملفات صحيحة وخاطئة، ونختبر المشروع باستخدام unittest، دون الحاجة إلى API حقيقي.
{alertInfo}قبل البدء: يفترض هذا الدرس إلمامك بالقواميس والقوائم وقراءة ملفات JSON. جميع بيانات الطلبات تجريبية. نستخدم مكتبة خارجية واحدة jsonschema، ويعمل المشروع محليًا بعد تثبيتها.كود البرنامج، ومخطط JSON Schema، وملفات بيانات صحيحة وخاطئة، مع اختبارات تلقائية وتعليمات تشغيل.
تحميل ملفات المشروع ZIP{getToc} $title={محتوى المقال}
ما الفرق بين JSON صحيح نحويًا وJSON مطابق لقواعد البرنامج؟
تؤدي json.load() وjson.loads() مهمة قراءة JSON. لكن نجاح القراءة يعني فقط أن النص يتبع قواعد كتابة JSON؛ لا يعني أن بياناته مناسبة لتطبيق المتجر أو واجهة API.
مثلًا، الكائن التالي JSON صالح نحويًا:
{
"name": "قلم",
"price": -50,
"quantity": "five"
}
ومع ذلك، قد يرفضه برنامجنا لأن price لا يُسمح أن يكون سالبًا وquantity يجب أن يكون عددًا صحيحًا.
| الموقف | نوع التحقق | الخطأ المتوقع |
|---|---|---|
| علامات تنصيص مفقودة أو فاصلة زائدة | JSON parsing | JSONDecodeError |
ملف JSON مقروء لكن حقل quantity نص | Schema validation | ValidationError |
| تعريف قواعد Schema غير صحيح | Schema validation | SchemaError |
شرحنا أسباب خطأ الصياغة في درس حل JSONDecodeError عند قراءة ملفات JSON. أما هذا الدرس فيركز على التحقق من بنية البيانات بعد قراءتها، دون إعادة شرح load وloads المطول الموجود في الفرق بين load وloads وdump وdumps.
ما JSON Schema؟ ولماذا نستخدم مكتبة jsonschema؟
JSON Schema طريقة لتعريف شكل البيانات المسموح به. تحدد هل القيمة كائنًا أو قائمة أو نصًا أو عددًا، وما المفاتيح الإلزامية، والحدود الرقمية، والعناصر المطلوبة داخل القوائم. لا يلزم أن تكتب عشرات شروط if المتفرقة؛ يكفي تعريف القواعد في ملف مستقل وإعادة استخدامها.
سنستعمل الصيغة Draft 2020-12، مع مكتبة Python jsonschema. تدعم المكتبة validate() للحالة البسيطة وDraft202012Validator.iter_errors() لجمع الأخطاء. فحص format يحتاج تفعيل FormatChecker صراحةً.
تثبيت jsonschema وتجهيز ملفات المشروع
أنشئ مجلدًا للمشروع، وافتح الطرفية بداخله، ثم شغّل:
python -m pip install "jsonschema>=4.22,<5"
ستجد في الحزمة الملفات: validator_app.py، وorder.schema.json، ومجلد samples للبيانات، ومجلد tests للاختبارات، وملف README.md.
{alertInfo}قد يظهر عند تشغيلpipأكثر من اسم مكتبة تبعية؛ هذا طبيعي. للتأكد من البيئة النشطة، استخدمpython -m pipبدل تثبيت الحزمة في مفسر مختلف.
كتابة أول JSON Schema للتحقق من أنواع البيانات
ابدأ بمخطط صغير يفرض أن اسم المنتج نص، والسعر رقم غير سالب، والكمية عدد صحيح يساوي 1 أو أكثر:
from jsonschema import validate
from jsonschema.exceptions import ValidationError
schema = {
"type": "object",
"required": ["name", "price", "quantity"],
"properties": {
"name": {"type": "string", "minLength": 1},
"price": {"type": "number", "minimum": 0},
"quantity": {"type": "integer", "minimum": 1},
},
}
product = {"name": "قلم", "price": 3.5, "quantity": 2}
try:
validate(instance=product, schema=schema)
print("البيانات مطابقة للشروط")
except ValidationError as error:
print("البيانات غير مطابقة:", error.message)
مخرجات هذا المثال عند تشغيله:
البيانات مطابقة للشروط
إذا غيّرت quantity إلى النص "two" فلن يطابق القيمة نوع integer؛ وسيعرض الاستثناء توضيحًا للقاعدة المخالفة. تفيد هذه الطريقة للبيانات الصغيرة عندما يكفي اكتشاف خطأ واحد.
معنى required وproperties وtype وminimum
نفهم الآن أهم الكلمات المستخدمة في المخطط:
| القاعدة | وظيفتها | مثال |
|---|---|---|
type | تحديد نوع القيمة | "integer" للكمية |
properties | تعريف شروط مفاتيح الكائن | price يجب أن يكون رقمًا |
required | تحديد المفاتيح التي لا يجوز غيابها | "customer" |
minimum | تعيين الحد العددي الأدنى | 0 للسعر |
minLength | الحد الأدنى لطول النص | 1 لرمز المنتج |
enum | قائمة قيم مسموحة فقط | "new" أو "shipped" |
additionalProperties | السماح أو عدم السماح بمفاتيح غير معرفة | false لمنع الإضافات |
معلومة مهمة: properties وحدها لا تجعل الحقل إلزاميًا. يجب إدراج اسمه في required إذا أردت رفض البيانات التي لا تحتويه. وبالمثل، تكون الحقول الإضافية مسموحة افتراضيًا ما لم تُقيّد.
إنشاء ملف Schema كامل لطلب متجر
نريد مخططًا لطلب يحتوي رقم الطلب، وبيانات العميل (الاسم والبريد)، وقائمة المنتجات مع sku وquantity وprice، وحالة اختيارية للطلب. هذا هو ملف order.schema.json الكامل الموجود في الحزمة:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "نموذج طلب متجر",
"type": "object",
"required": ["order_id", "customer", "items"],
"properties": {
"order_id": {"type": "string", "minLength": 1},
"customer": {
"type": "object",
"required": ["name", "email"],
"properties": {
"name": {"type": "string", "minLength": 2},
"email": {"type": "string", "format": "email"}
},
"additionalProperties": false
},
"items": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["sku", "quantity", "price"],
"properties": {
"sku": {"type": "string", "minLength": 1},
"quantity": {"type": "integer", "minimum": 1},
"price": {"type": "number", "minimum": 0}
},
"additionalProperties": false
}
},
"status": {"type": "string", "enum": ["new", "processing", "shipped"]}
},
"additionalProperties": false
}
لاحظ استخدام items في موضعين: الأولى اسم حقل الطلب الذي يحتوي قائمة المنتجات، والثانية قاعدة JSON Schema التي تصف العناصر داخل تلك القائمة. استخدام الاسمين هنا صحيح لأنه يحدث على مستويين مختلفين.
تجهيز ملفات JSON الصحيحة والخاطئة للتجربة
الملف الأول samples/valid-order.json يمثل طلبًا مطابقًا للشروط:
{
"order_id": "ORD-1001",
"customer": {"name": "سارة", "email": "sara@example.com"},
"items": [
{"sku": "BOOK-1", "quantity": 2, "price": 15.5},
{"sku": "PEN-2", "quantity": 1, "price": 3}
],
"status": "new"
}
أما الملف الثاني samples/invalid-order.json فهو صحيح نحويًا، لكنه يحتوي على أخطاء مقصودة:
{
"customer": {"name": "سارة", "email": "not-an-email"},
"items": [
{"sku": "BOOK-1", "quantity": "two", "price": -15},
{"sku": "PEN-2", "quantity": 0, "price": 3}
],
"status": "unknown",
"coupon": "SALE"
}
أهم الاختلافات: حقل order_id مفقود، والبريد لا يطابق صيغة البريد الإلكتروني، والكمية الأولى نص، والسعر الأول سالب، والكمية الثانية صفر، وحالة الطلب غير مسموحة، وهناك حقل إضافي اسمه coupon.
التحقق من الحقول المطلوبة والبيانات المتداخلة
لا يكفي أن يكون customer موجودًا؛ يجب أن يحتوي بدوره على name وemail. وينطبق الأمر ذاته على كل عنصر من قائمة items. هكذا نكتب مخططًا يمكنه فحص بيانات متداخلة دون تكرار شروط يدويًا لكل طلب:
from jsonschema import Draft202012Validator
schema = {
"type": "object",
"required": ["customer"],
"properties": {
"customer": {
"type": "object",
"required": ["name", "email"],
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
},
}
},
}
data = {"customer": {"name": "سارة"}}
errors = list(Draft202012Validator(schema).iter_errors(data))
for error in errors:
print(error.json_path, error.message)
لاحظ أن موضع قاعدة required في نتيجة error.json_path يشير إلى الكائن الذي ينقصه المفتاح، وليس بالضرورة إلى المفتاح غير الموجود نفسه. في مشروعنا سنضيف اسم المفتاح إلى المسار عندما نستطيع استخراجه بصورة موثوقة، مع الاحتفاظ برسالة الخطأ الأصلية.
كيف نتحقق من البريد الإلكتروني باستخدام FormatChecker؟
وضع "format": "email" في Schema لا يكفي وحده لتفعيل الفحص باستخدام مكتبة jsonschema عند إنشاء المدقق دون خيارات. لتطبيق هذا النوع من القواعد، نمرر FormatChecker():
from jsonschema import Draft202012Validator, FormatChecker
schema = {"type": "string", "format": "email"}
validator = Draft202012Validator(
schema,
format_checker=FormatChecker(),
)
errors = list(validator.iter_errors("not-an-email"))
print("أخطاء تنسيق البريد:", len(errors))
أخطاء تنسيق البريد: 1
{alertWarning}مهم: نتيجةFormatCheckerتعني أن النص اجتاز أو فشل في فحص صيغة البريد الذي ينفذه المدقق المتاح؛ لا تثبت أن العنوان موجود فعلًا أو يستطيع استقبال الرسائل. بعض صيغformatالأخرى تحتاج تبعيات اختيارية، لذلك تحقق من المكتبات المطلوبة قبل الاعتماد عليها.
عرض جميع أخطاء JSON باستخدام iter_errors()
تتوقف دالة validate() عند أول مخالفة تكتشفها، بينما يفيد iter_errors() إذا أردت سرد المشاكل التي يجدها المدقق في عملية واحدة. في مشروعنا نستخدم Draft202012Validator.check_schema() قبل إنشاء المدقق، ثم نجمع الأخطاء ونرتبها حسب مسار الحقل ونوع القاعدة.
import json
from jsonschema import Draft202012Validator, FormatChecker
with open("order.schema.json", encoding="utf-8") as file:
schema = json.load(file)
with open("samples/invalid-order.json", encoding="utf-8") as file:
data = json.load(file)
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(
schema,
format_checker=FormatChecker(),
)
for error in validator.iter_errors(data):
print(error.json_path, "|", error.validator, "|", error.message)
قد يختلف ترتيب ظهور الأخطاء في هذا المثال المختصر تبعًا لترتيب المرور على القواعد، لذلك يوفر البرنامج الكامل ترتيبًا ثابتًا قبل طباعة التقرير.
كيف نفهم مسار الخطأ داخل JSON؟
يعرض الكائن ValidationError خصائص مفيدة هي json_path وpath وvalidator وmessage. وفي بيانات الطلب المتداخل، قد تعني المسارات:
| المسار | معناه |
|---|---|
$.customer.email | حقل البريد داخل بيانات العميل |
$.items[0].quantity | كمية المنتج الأول |
$.items[1].quantity | كمية المنتج الثاني |
$.order_id | رقم الطلب المفقود؛ أضاف برنامجنا اسم الحقل إلى مسار الكائن |
$ | جذر كائن الطلب؛ يظهر مثلًا عند مخالفة additionalProperties |
لهذا لا ينبغي اختلاق مسار دقيق لكل خطأ. عندما يفشل شرط additionalProperties يُبلّغ المدقق عادةً عن الكائن الحاوي للخاصية الإضافية، ويذكر اسمها داخل الرسالة نفسها. وكذلك يعتمد اشتقاق اسم الحقل المفقود من رسالة required على صيغة الرسالة، ولهذا يستخدم مشروعنا طريقة محافظة مع مسار بديل.
مشروع متكامل: التحقق من ملف JSON وإنشاء تقرير بالأخطاء
الآن ننتقل إلى البرنامج الكامل validator_app.py. يمكن تمرير مسار ملف البيانات ومسار المخطط، وإضافة --report للحصول على تقرير JSON قابل للمعالجة لاحقًا. يحمي البرنامج ملفي الإدخال من الكتابة فوقهما إذا استخدمت مسار تقرير مطابقًا لأحدهما.
يتضمن البرنامج أربع وظائف رئيسية:
read_json()لقراءة الملف والتحقق من صحة الصياغة.describe_error()لتنسيق الخطأ ومسار الحقل.validate_data()للتحقق من صحة الـSchema ثم جمع الأخطاء.cli()لتشغيل المشروع وإدارة رسائل الأخطاء والتقرير.
هذا هو ملف البرنامج الكامل نفسه المرفق في ZIP:
"""Validate JSON documents with a local Draft 2020-12 schema.
Python 3.10+, jsonschema 4.x. Never modifies the input files.
Exit statuses: 0 = valid; 1 = data violates schema; 2 = operational/schema error.
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
import re
import sys
from jsonschema import Draft202012Validator, FormatChecker
from jsonschema.exceptions import SchemaError, ValidationError
def read_json(path: Path):
"""Return one JSON value; fail clearly for malformed JSON or invalid UTF-8."""
with path.open("r", encoding="utf-8-sig") as handle:
return json.load(handle)
def describe_error(error: ValidationError) -> dict[str, str]:
"""Return the actual jsonschema path, with a helpful missing-field suffix.
For 'required', jsonschema reports the containing object as `path`.
We add the omitted field only when its name can be reliably extracted.
"""
path = error.json_path
missing = None
if error.validator == "required":
match = re.fullmatch(r"'([^']+)' is a required property", error.message)
if match:
missing = match.group(1)
if isinstance(error.instance, dict) and missing not in error.instance:
path += f".{missing}" if missing.isidentifier() else f"[{json.dumps(missing, ensure_ascii=False)}]"
return {
"path": path,
"rule": str(error.validator),
"message": error.message,
}
def validate_data(data, schema) -> list[dict[str, str]]:
"""Check schema once; collect ALL top-level violations in stable order."""
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema, format_checker=FormatChecker())
errors = [describe_error(error) for error in validator.iter_errors(data)]
return sorted(errors, key=lambda row: (row["path"], row["rule"], row["message"]))
def save_report(output: Path, problems: list[dict[str, str]]) -> None:
report = {
"valid": not bool(problems),
"error_count": len(problems),
"errors": problems,
}
output.parent.mkdir(parents=True, exist_ok=True)
with output.open("w", encoding="utf-8") as handle:
json.dump(report, handle, ensure_ascii=False, indent=2)
handle.write("\n")
def cli(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="فحص بيانات JSON وفق JSON Schema محلي")
parser.add_argument("--data", type=Path, default=Path("samples/invalid-order.json"))
parser.add_argument("--schema", type=Path, default=Path("order.schema.json"))
parser.add_argument("--report", type=Path, default=None, help="مسار اختياري لحفظ تقرير JSON")
args = parser.parse_args(argv)
# Never risk overwriting source data or its schema with a report.
if args.report and args.report.resolve() in {args.data.resolve(), args.schema.resolve()}:
print("خطأ: مسار التقرير يجب أن يختلف عن مساري البيانات والمخطط.", file=sys.stderr)
return 2
try:
schema = read_json(args.schema)
Draft202012Validator.check_schema(schema)
data = read_json(args.data)
errors = validate_data(data, schema)
except FileNotFoundError as exc:
print(f"ملف غير موجود: {exc.filename}", file=sys.stderr)
return 2
except PermissionError as exc:
print(f"لا توجد صلاحية لقراءة الملف: {exc.filename}", file=sys.stderr)
return 2
except json.JSONDecodeError as exc:
print(f"JSON غير صحيح نحويًا: السطر {exc.lineno}، العمود {exc.colno}: {exc.msg}", file=sys.stderr)
return 2
except (SchemaError, UnicodeError, OSError) as exc:
print(f"تعذر إكمال التحقق: {exc}", file=sys.stderr)
return 2
if not errors:
print("VALID: البيانات مطابقة للمخطط (0 أخطاء).")
else:
print(f"INVALID: تم اكتشاف {len(errors)} أخطاء:")
for num, item in enumerate(errors, 1):
print(f"{num}. {item['path']} [{item['rule']}] {item['message']}")
if args.report:
try:
save_report(args.report, errors)
print(f"تم حفظ التقرير: {args.report}")
except OSError as exc:
print(f"تعذر حفظ التقرير: {exc}", file=sys.stderr)
return 2
return 1 if errors else 0
if __name__ == "__main__":
raise SystemExit(cli())
تشغيل المشروع ومشاهدة مخرجات الاختبار الفعلية
بعد تثبيت المتطلبات، افتح الطرفية من مجلد المشروع. لقراءة طلب صحيح، شغّل:
python validator_app.py --data samples/valid-order.json
المخرجات التي حصلنا عليها فعلًا:
$ python validator_app.py --data samples/valid-order.json
VALID: البيانات مطابقة للمخطط (0 أخطاء).
Exit code: 0
ولفحص الطلب الخاطئ وحفظ تقرير مفصل:
python validator_app.py --data samples/invalid-order.json --report sample-report.json
المخرجات الفعلية على ملف العينة غير الصحيح:
$ python validator_app.py --data samples/invalid-order.json --report sample-report.json
INVALID: تم اكتشاف 7 أخطاء:
1. $ [additionalProperties] Additional properties are not allowed ('coupon' was unexpected)
2. $.customer.email [format] 'not-an-email' is not a 'email'
3. $.items[0].price [minimum] -15 is less than the minimum of 0
4. $.items[0].quantity [type] 'two' is not of type 'integer'
5. $.items[1].quantity [minimum] 0 is less than the minimum of 1
6. $.order_id [required] 'order_id' is a required property
7. $.status [enum] 'unknown' is not one of ['new', 'processing', 'shipped']
تم حفظ التقرير: sample-report.json
Exit code: 1
اكتشف البرنامج 7 مخالفات من فئات متعددة؛ ولم يتوقف بعد أول خطأ. لاحظ أن رسالة التفاصيل الإنجليزية تأتي من مكتبة jsonschema نفسها، بينما أضفنا مقدمة عربية ومسارًا واضحًا لكل مخالفة. وتستخدم الأداة المسار $ لمخالفة الخاصية الإضافية لأن المدقق أبلغ عن الكائن الأصلي.
أما sample-report.json فيحتوي المفاتيح valid وerror_count وerrors، ويضم كل خطأ كعنصر مستقل بقيم path وrule وmessage. يُحفظ التقرير باستخدام UTF-8 مع الحفاظ على العربية.
الفرق العملي بين JSONDecodeError وValidationError وSchemaError
أنشأنا ملفًا ثالثًا باسم samples/broken-syntax.json يحتوي أقواسًا غير مكتملة. عند تشغيله، لا يصل البرنامج أصلًا إلى خطوة التحقق من الحقول:
python validator_app.py --data samples/broken-syntax.json
$ python validator_app.py --data samples/broken-syntax.json
JSON غير صحيح نحويًا: السطر 4، العمود 1: Expecting value
Exit code: 2
في المقابل، يطلق SchemaError عندما تكون قواعد المخطط نفسها مخالفة لمواصفة الـDraft المستخدمة، ككتابة نوع غير معروف مثل "type": "nonsense". لذلك نتحقق من الـSchema قبل استعماله، ولا نخلط بين خطأ في المخطط وخطأ في بيانات المستخدم.
يرجع برنامجنا رمز خروج 0 عند نجاح التحقق، و1 عند وجود مخالفات في البيانات، و2 عند فشل قراءة الملفات أو صياغة JSON أو صحة المخطط أو حفظ التقرير. يفيد ذلك إذا أردت استعماله لاحقًا داخل سكربت آلي.
كيف نختبر المشروع باستخدام unittest؟
تتضمن الحزمة اختبارات مستقلة باستخدام مكتبة unittest القياسية. نفحص بها البيانات السليمة والمخالفة، والتحقق من صيغة البريد، والمفاتيح الإلزامية، والقوائم المتداخلة، وأخطاء الصياغة، وإنشاء التقرير، ورموز الخروج، ومنع الكتابة فوق ملفات الإدخال.
للتشغيل من مجلد المشروع:
python -m unittest discover -s tests -v
نجحت 23 من 23 اختبارًا أثناء إعداد المشروع باستخدام إصدار jsonschema 4.26.0 وPython 3.13.5. هذه اختبارات للكود وملفات العينة المرفقة، ولا تعني ضمان سلامة أي بيانات خارجية أو أي مخطط يُقدّمه المستخدم.
أخطاء شائعة عند استخدام jsonschema ونصائح مهمة
| الحالة | السبب | الحل |
|---|---|---|
ModuleNotFoundError | ثبتت الحزمة في بيئة مختلفة | python -m pip install -r requirements.txt في البيئة الحالية |
| لا يظهر خطأ في البريد | لم يُمرّر FormatChecker | مرره عند إنشاء Validator |
| لا يظهر خطأ عند غياب مفتاح | المفتاح في properties فقط | أضفه إلى required |
| تُقبل المفاتيح غير المتوقعة | عدم تحديد additionalProperties | استخدم false عند الحاجة |
خطأ JSONDecodeError | الملف ليس JSON صحيحًا نحويًا | أصلح التنصيص والفواصل والأقواس قبل التحقق |
خطأ SchemaError | تعريف قاعدة غير مطابق للمواصفة | شغّل check_schema() |
مسار required يظهر للكائن فقط | اسم الحقل مفقود من البيانات | اقرأ error.message بجانب مسار الكائن |
لا تخلط التحقق البنيوي مع الحماية الأمنية الشاملة: فقد تكون البيانات مطابقة لـSchema لكنها غير موثوقة لأسباب أخرى. تعامل بحذر مع ملفات Schema تأتي من مصادر غير معروفة، خصوصًا إذا تضمنت مراجع خارجية، ولا تعرض تقارير JSON تحتوي بيانات شخصية على صفحات عامة.
روابط موثوقة للتوسع في JSON Schema
- التوثيق الرسمي لمكتبة jsonschema: التحقق من المخططات وتفعيل FormatChecker.
- شرح ValidationError وjson_path في التوثيق الرسمي.
- مرجع JSON Schema للمفاتيح required وproperties وadditionalProperties.
- قراءة وكتابة JSON في بايثون: الفرق بين load وloads وdump وdumps.
- حل خطأ JSONDecodeError عند قراءة ملفات JSON.
الأسئلة الشائعة حول التحقق من JSON في بايثون
هل json.load() يكفي للتحقق من صحة JSON؟
لا. يتأكد json.load() من أن النص يمكن تفسيره بصيغة JSON، لكنه لا يتحقق من وجود order_id أو صحة price أو نوع quantity. هذه مهمة JSON Schema.
هل مكتبة jsonschema تحتاج إلى الإنترنت عند التشغيل؟
بعد تثبيتها، يمكن استخدام المخططات والبيانات المحلية دون اتصال بالشبكة. لكن مخططات أخرى تحتوي على مراجع خارجية $ref قد تتطلب ترتيبات إضافية للمراجع؛ لا نفترض أن جميع المخططات تعمل دون اتصال.
كيف أعرض جميع الأخطاء بدل الخطأ الأول؟
استخدم Draft202012Validator(schema).iter_errors(data)، ثم رتّب المخالفات واعرض error.json_path وerror.validator وerror.message. ولتطبيق format مرر FormatChecker().
لماذا لا يظهر اسم الحقل المفقود دائمًا في error.path؟
لأن الحقل المفقود لا وجود له داخل البيانات، فتشير قاعدة required عادةً إلى الكائن الأب. يعرض المشروع اسم الحقل من رسالة المكتبة عند إمكانية استخراجه بصورة موثوقة.
هل additionalProperties يمنع الحقول الجديدة تلقائيًا؟
لا. السماح بالحقول الإضافية هو السلوك الافتراضي. استخدم "additionalProperties": false داخل تعريف الكائن الذي تريد منع المفاتيح غير المتوقعة فيه.
هل FormatChecker يضمن أن البريد الإلكتروني صحيح وقابل للاستخدام؟
لا. يختبر المدقق صيغة القيمة وفق فاحصه المتاح، لكنه لا يختبر وجود صندوق البريد أو قدرة صاحبه على استقبال الرسائل. قد تتطلب قيود أخرى إجراءات تحقق إضافية.
ما الفرق بين ValidationError وSchemaError؟
ValidationError يعني أن بيانات الإدخال لا تطابق مخططًا صحيحًا، أما SchemaError فيعني أن تعريف المخطط نفسه مخالف للمواصفة. ويتعلق JSONDecodeError بصياغة JSON قبل الفحص البنيوي.
هل أستطيع التحقق من بيانات API باستخدام المشروع؟
نعم بعد تحويل الاستجابة إلى بيانات Python مثل dict أو list، وإعداد مخطط يطابق العقد المتوقع لـAPI. لكن نسخة المشروع الحالية تقرأ ملفات JSON محلية ولا ترسل أي طلب HTTP تلقائيًا.


![التحقق من الحقول المطلوبة والأنواع والقيم داخل JSON Schema في بايثون شرح التحقق من الحقول المتداخلة في JSON Schema مثل order_id وcustomer.email وitems[].quantity باستخدام required وtype وminimum](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXqa3JxKMWBkFrQXKhJErk6YIupYenPsDN_weQDB951xK2OQnOWZuWs2_U-5OAw87F_UA85_CGYmHDIeQ7RzJ6ROsb5JrgulXj7jwD2NdSovAsKI4UhPMDehTUKvwPkCUuZMJIYc5S0h5oi9HfE2lcfCtyPb258bg_v7mYITTOXAYz6_QEX2SwCcUKh0Q/s1600-rw/python-jsonschema-nested-order-fields.webp)
