بدون additionalProperties، اعتبارسنجی اسکیما هیچچیز را اعتبارسنجی نمیکند
جمعبندی: قبولی اعتبارسنجی به معنای داده تمیز نیست. Pydantic بهطور پیشفرض فیلدهای ناشناخته را نادیده میگیرد، Zod آنها را حذف میکند و Ajv رد میکند — پارامترهای توهمی و کلیدهای غلط املایی بیصدا عبور میکنند. این مقاله سه شکل پذیرش بیصدا را نشان میدهد و دستور کامل میدهد: بستن اشیا، کنترل تبدیل نوع، سفتکردن هر سطح تودرتو.

نتیجه: بهطور پیشفرض اعتبارسنجها فیلدهای اعلاننشده را نادیده میگیرند نه رد کنند. بدون additionalProperties: false، قبولی فقط اثبات میکند فیلدهای اعلامشده سالماند.
خطرناکترین رفتار اعتبارسنج نه خطا دادن، بلکه سکوت است. یک کلید غلط یا پارامتر ساختهشده توسط مدل بیصدا از اعتبارسنجی میگذرد و در منطق کسبوکار منفجر میشود.
یک: اعتبارسنجیای که «قبول» میشود
{
"type": "object",
"properties": {
"order_id": { "type": "string" },
"amount": { "type": "number" }
},
"required": ["order_id", "amount"]
}
{"order_id": "A1", "amount": 50, "reasn_code": "damaged"} را بفرستید — کلید سوم غلط املایی است. با پیکربندی پیشفرض Ajv نتیجه قبولی است. فیلد اضافی نه رد میشود نه علامتگذاری.
در مشخصات JSON Schema مقدار پیشفرض additionalProperties برابر true است: فیلدهای اعلاننشده مجازند.
دو: سه شکل سکوت
| محیط اجرا | رفتار پیشفرض | نتیجه |
|---|---|---|
| Ajv (JS) | عبور میدهد | داده کثیف به منطق میرسد |
Zod z.object |
حذف میکند | فیلد ناپدید میشود، شیء کوتاهتر میشود |
| Pydantic v2 | نادیده میگیرد (extra="ignore") |
همان، بدون ردپا در لاگها |
حذف پنهانکارانهتر از عبور است. هر دو کتابخانه بهطور پیشفرض به شکل یکسانی — بیصدا — شکست میخورند.
سه: فراخوانی ابزار LLM مشکل را بزرگتر میکند
آرگومانها را مدل تولید میکند: نام فیلدها را از خودش میسازد و "3" را بهجای عدد میفرستد. پلتفرمها پارامترها را با JSON Schema تعریف میکنند اما بهطور پیشفرض بستهبودن اسکیما را الزامی نمیکنند — حالت strict باید صریح فعال شود و محدودیتهای دستوری فقط خروجی مستقیم مدل را پوشش میدهند.
{
"order_id": 4411,
"refund_amount_usd": 50,
"reason_code": "damaged",
"urgent": "yes"
}
با بستهبودن شیء، reason_code و urgent رد میشوند و خطا به مسیر /reason_code اشاره میکند.
چهار: چگونه ببندیم
Ajv: additionalProperties: false را روی گره شیء اضافه کنید.
import Ajv from "ajv";
const ajv = new Ajv({ allErrors: true });
const schema = {
type: "object",
properties: { order_id: { type: "string" }, amount: { type: "number" } },
required: ["order_id", "amount"],
additionalProperties: false,
};
const validate = ajv.compile(schema);
validate({ order_id: "A1", amount: 50, reasn_code: "x" }); // false
Zod: z.strictObject یا .strict(). Pydantic: ConfigDict(extra="forbid").
قاعده مشترک: بستن در هر سطح انجام میشود. هر شیء تودرتو به additionalProperties: false خودش نیاز دارد.
پنج: سیاست تبدیل نوع
حالت lax در Pydantic "5" را به 5 تبدیل میکند. سه سیاست: سختگیرانه (رد انواع غلط)، کنترلشده (فقط تبدیلهای صریح و محدود)، آزاد (فقط داده داخلی). برای ورودیهای غیرقابلاعتماد اول یا دوم را انتخاب و در تستها ثبت کنید.
شش: چکلیست تودرتویی
| نقطه | اقدام |
|---|---|
| شیء ریشه | additionalProperties: false |
| هر شیء تودرتو | همان |
| عناصر آرایه | اشیای داخل items را ببندید |
| Enum و بازه | افزودن enum، minimum/maximum |
| اسکیمای تولیدی | بهصورت دستی کامل کنید |
هفت: پس از ردشدن
allErrors: true همه فیلدها را یکجا گزارش میکند؛ verbose: true مسیرها را میدهد. مشکلات نحوی را پارسر پیش از اعتبارسنجی اسکیما میگیرد.
پرسشهای متداول
زیاد سختگیرانه نیست؟
به قرارداد بستگی دارد. برای ورودی خودتان ببندید؛ برای داده شخص ثالث با قابلیت توسعه، فقط هسته را ببندید و ناحیه توسعه را جدا کنید.
حذف (strip) در Zod امنتر نیست؟
نه: از پاییندست محافظت میکند به قیمت ضرر برای فراخوان. خطاها باید زود و صریح ظاهر شوند.
حالت strict پلتفرم جای اعتبارسنجی محلی را میگیرد؟
نه. خود اسکیما میتواند باز باشد و دستور زبان ممکن است آرگومانهای ابزار را پوشش ندهد.
بعد از بستن، دادههای قدیمی دستهای رد میشوند؟
دقیقاً همان چیزی است که باید آشکار شود. با allErrors فهرست کنید، فیلدهای بیضرر را اضافه و مضرها را اصلاح کنید.
راهحل یکخطی؟
نه، اما حداقل اقدام: بررسی کنید که هر type: "object" با additionalProperties: false همراه است.