null หรือไม่ใส่ฟิลด์
สรุปสำคัญ: `null` บอกว่าฟิลด์มีอยู่แต่ไม่มีค่า; การไม่ใส่ฟิลด์บอกว่าฟิลด์ไม่มีอยู่ PATCH body การ merge config และการเติมฟอร์มคือจุดที่ความต่างนี้สำคัญ

สรุปสั้น ๆ: ส่ง null เมื่อผู้ใช้ข้อมูลต้องแยก "ถูกล้าง" จาก "ไม่ถูกแตะต้อง" — ใน PATCH body การไม่ใส่ฟิลด์ปล่อยไว้เหมือนเดิมและ null ที่ชัดเจนล้างมัน — และใช้ข้อกำหนดเดียวต่อฟิลด์เพื่อให้ response และการ merge config คงที่
ความต่าง
{ "nickname": null }
มีอยู่ แต่ว่าง ผู้ใช้ข้อมูลรู้ว่าฟิลด์ถูกล้างอย่างชัดเจน
{ }
ไม่มีอยู่ ผู้ใช้ข้อมูลแยก "ไม่เคยตั้งค่า" กับ "ไม่รองรับ" ไม่ได้
ใน JavaScript ความต่างนี้เป็นรูปธรรม:
'nickname' in obj // false — ไม่มีฟิลด์
obj.nickname === null // true — มีฟิลด์และเป็น null
obj.nickname === undefined // true — ทั้งสองกรณี
จุดที่ความต่างนี้สำคัญ
PATCH body {"nickname": null} ล้าง nickname {} ไม่เปลี่ยนอะไร ถ้า handler ถือว่า "null" กับ "ไม่มี" เหมือนกัน ผู้ใช้จะไม่มีทางล้างฟิลด์ได้เลย — ทำได้แค่ตั้งสตริงว่าง ซึ่งเป็นอีกเรื่องหนึ่ง
ทำให้เป็นโค้ดด้วยการตรวจการมีอยู่ของคีย์ ไม่ใช่ค่า:
if (Object.hasOwn(patch, 'nickname')) {
target.nickname = patch.nickname; // null allowed
}
การ merge config การไม่ใส่สืบทอดค่าเริ่มต้น; null ปิดใช้งานอย่างชัดเจน นี่คือพฤติกรรมของ values ใน Helm และ Kubernetes พอดี
การเติมฟอร์ม null แสดงเป็นว่างและฟิลด์ที่ไม่มีก็เช่นกัน แต่การ submit ต่างกัน: เคยมีค่า ตอนนี้ล้างแล้ว → ส่ง null; ไม่เคยกรอก → ไม่ใส่ฟิลด์ ถ้าไม่มีความต่างนี้ การล้างจะดูเหมือนการไม่แตะต้อง
ข้อกำหนด
| สถานการณ์ | ข้อกำหนด |
|---|---|
| Response body | เก็บ null; รูปร่างคงที่ type ง่ายกว่า |
| PATCH request | null ล้าง, การไม่ใส่คงไว้ |
| PUT (แทนที่ทั้งหมด) | การไม่ใส่หมายถึงลบ — เอกสารทั้งก้อนถูกแทนที่ |
| Merge config | ไม่ใส่ = ค่าเริ่มต้น, null = ปิดใช้งาน |
| ฐานข้อมูล | null สำหรับค่าที่ไม่รู้หรือไม่เกี่ยวข้อง; '' สำหรับค่าว่างที่รู้แน่ |
ให้รูปร่าง response คงที่ list ที่บางรายการมี avatar และบางรายการไม่มีบังคับให้ตรวจ 'avatar' in item ทุกจุดที่เรียกใช้ avatar: null ใช้งานง่ายกว่า
สามสิ่งที่ไม่ควรทำ
อย่าใช้ "" แทน null nickname ว่างกับ nickname ที่ยังไม่ตั้งเป็นสถานะต่างกันในโดเมนส่วนใหญ่
อย่าใช้ 0 หรือ -1 เป็น sentinel ศูนย์เป็นตัวเลขที่ถูกต้อง และ sentinel จะทำให้ค่าเฉลี่ยทุกค่าที่คำนวณเพี้ยน
อย่าผสมข้อกำหนดต่อ endpoint สองข้อกำหนดหมายถึงสองเส้นทางโค้ดในทุกไคลเอนต์
คำถามที่พบบ่อย
อะไรเป็นตัวตัดสินระหว่าง null กับฟิลด์ที่ไม่ใส่?
ถามว่าผู้ใช้ข้อมูลต้องแยก "ถูกล้างอย่างชัดเจน" จาก "ไม่เคยตั้งค่า" หรือไม่ ใน PATCH body ต้องแยก จึงใช้ null ล้างและการไม่ใส่คงไว้; ใน response การเก็บ null ทำให้รูปร่างคงที่และ type ของไคลเอนต์ง่ายกว่า
Endpoint PATCH แยกการล้างออกจากการปล่อยไว้ได้อย่างไร?
ตรวจการมีอยู่ของคีย์ ไม่ใช่ค่า: Object.hasOwn(patch, 'nickname') บอกว่าฟิลด์ถูกส่งมา และเฉพาะเมื่อถึงตอนนั้นจึงกำหนดค่า รวมถึง null ถ้า handler ถือว่า null กับไม่มีเหมือนกัน ผู้ใช้จะไม่มีทางล้างฟิลด์ได้และทำได้แค่ถอยไปใช้สตริงว่าง
ทำไม response body ควรเก็บ null ไว้?
รูปร่างที่คงที่หมายความว่าไคลเอนต์ไม่ต้องตรวจ 'avatar' in item ทุกคีย์ optional เมื่อบางรายการใน list มี avatar และบางรายการไม่ใส่ การตรวจนั้นถูกทำซ้ำทุกจุดที่เรียกใช้และทำผิดได้ง่าย