JSON Toolkit

Tanpa additionalProperties, pengesahan skema tidak mengesahkan apa-apa

Inti pati: Pengesahan yang lulus tidak bermakna data bersih. Pydantic secara lalai mengabaikan medan asing, Zod mengalihkannya, Ajv membiarkannya — parameter halusinasi dan kunci tersilap lolos tanpa bunyi. Artikel ini menunjukkan tiga bentuk penerimaan senyap dan memberikan resipi lengkap: menutup objek, mengawal paksaan jenis, menggenggam setiap peringkat bersarang.

Intermediate~8 min bacaanDiterbitkan 2026-11-02Dikemas kini 2026-11-02
JSON dengan medan tambahan lulus pengesahan

Kesimpulan: secara lalai, pengesah mengabaikan medan yang tidak diisytiharkan dan bukannya menolaknya. Tanpa additionalProperties: false, kelulusan hanya membuktikan medan yang diisytiharkan tidak bermasalah.

Perilaku paling berbahaya bagi pengesah bukanlah membuang ralat, tetapi mendiamkan diri. Kunci tersilap atau parameter yang direka oleh model lolos pengesahan tanpa bunyi dan meletup dalam logik perniagaan.

Satu: pengesahan yang "lulus"

{
  "type": "object",
  "properties": {
    "order_id": { "type": "string" },
    "amount": { "type": "number" }
  },
  "required": ["order_id", "amount"]
}

Hantar {"order_id": "A1", "amount": 50, "reasn_code": "damaged"} — kunci ketiga tersilap ejaan. Dengan konfigurasi lalai Ajv, hasilnya lulus. Medan tambahan tidak ditolak mahupun ditanda.

Dalam spesifikasi JSON Schema, nilai lalai additionalProperties ialah true: medan yang tidak diisytiharkan dibenarkan.

Dua: tiga bentuk senyap

Runtime Tingkah laku lalai Akibat
Ajv (JS) biar lulus data kotor sampai ke logik
Zod z.object alih keluar medan hilang, objek menjadi pendek
Pydantic v2 abaikan (extra="ignore") sama, tanpa jejak dalam log

Pembuangan lebih licik daripada kelulusan. Kedua-dua pustaka gagal secara senyap dengan cara yang sama, secara lalai.

Tiga: panggilan alat LLM membesarkan masalah

Argumen dijana oleh model: ia mereka nama medan dan menghantar "3" sebagai nombor. Platform mentakrifkan parameter sebagai JSON Schema tetapi secara lalai tidak memaksa skema ditutup — mod strict perlu diaktifkan secara jelas, dan kekangan tatabahasa hanya meliputi output terus model.

{
  "order_id": 4411,
  "refund_amount_usd": 50,
  "reason_code": "damaged",
  "urgent": "yes"
}

Dengan objek tertutup, reason_code dan urgent ditolak dan ralat menunjuk ke laluan /reason_code.

Empat: cara menutup

Ajv: tambah additionalProperties: false pada nod objek.

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: ganti z.object dengan z.strictObject atau rantaikan .strict(). Pydantic: konfigurasikan ConfigDict(extra="forbid").

Peraturan sama: penutupan dilakukan peringkat demi peringkat. Setiap objek bersarang perlu additionalProperties: false sendiri.

Lima: polisi paksaan jenis

Mod lax Pydantic menukar "5" kepada 5. Tiga polisi: ketat (tolak jenis salah), terkawal (hanya penukaran jelas bersempadan), bebas (data dalaman sahaja). Untuk input tidak dipercayai, pilih 1 atau 2 dan tulis dalam ujian.

Enam: senarai semak bersarang

Titik Tindakan
Objek akar additionalProperties: false
Setiap objek bersarang sama
Elemen tatasusunan tutup objek dalam items
Enum dan julat tambah enum, minimum/maximum
Skema janaan lengkapkan secara manual

Tujuh: selepas penolakan

allErrors: true melaporkan semua medan sekali gus; verbose: true memberikan laluan. Masalah sintaks disaring oleh penghurai sebelum pengesahan skema.

Soalan Lazim

Terlalu ketat?

Bergantung pada kontrak. Untuk input sendiri, tutup; untuk data pihak ketiga yang boleh diluaskan, tutup teras sahaja danasingkan kawasan sambungan.

Strip Zod bukannya lebih selamat?

Tidak: ia melindungi hilir dengan mengorbankan pemanggil. Ralat perlu muncul awal dan jelas.

Mod strict platform menggantikan pengesahan setempat?

Tidak. Skema sendiri mungkin terbuka dan tatabahasa mungkin tidak meliputi argumen alat.

Selepas menutup, data lama gagal beramai-ramai?

Itulah yang patut didedahkan. Senaraikan dengan allErrors, tambah medan tidak berbahaya, betulkan yang berbahaya.

Penyelesaian satu baris?

Tiada, tetapi langkah minimum: pastikan setiap type: "object" diikuti additionalProperties: false.