ทำไม trailing comma ถึงทำให้ JSON พัง
สรุปสำคัญ: trailing comma ถูกกฎใน object literal ของ JavaScript แต่เป็นเรื่องถึงตายใน JSON นี่คือ error ที่เกิดจริง ไวยากรณ์ RFC 8259 ที่เป็นสาเหตุ และวิธีแก้สามแบบที่ได้ผลจริง

สรุปสั้น ๆ: JSON ห้าม trailing comma ทุกที่ — เมื่อ parser ล้มเหลว ให้ใช้ formatter ลบคอมมาตัวสุดท้าย; ใช้ JSON5 หรือ JSONC เฉพาะการ parse แบบผ่อนปรนในเครื่อง และส่ง JSON มาตรฐานให้ระบบอื่นเสมอ
เพราะไวยากรณ์กำหนดไว้อย่างนั้น
{
"name": "demo",
"size": 12,
}
JSON.parse throw Unexpected token } in JSON at position 34 Node ใช้ถ้อยคำต่างออกไป แต่ทุก engine ชี้จุดเดียวกัน: comma ก่อน }
parser กำลังบ่นเรื่องอะไรกันแน่
production ของ object ใน RFC 8259 คือ:
object = begin-object [ member *( value-separator member ) ] end-object
วงเล็บเหลี่ยมหมายถึงไม่บังคับ ดอกจันหมายถึงศูนย์ครั้งหรือมากกว่า พูดง่าย ๆ: comma คั่นสมาชิก และสมาชิกตัวสุดท้ายตามด้วย } ตรง ๆ
ดังนั้นหลัง comma parser พร้อมจะอ่านชื่อสมาชิกอีกตัว แต่กลับอ่านเจอ } จึงล้มเหลว array ก็ทำงานเหมือนกัน — [1, 2, 3,] ล้มเหลวที่ ]
นิสัยนี้มาจากไหน
object literal ของ JavaScript อนุญาต trailing comma ตั้งแต่ ES5 เช่นเดียวกับ list ของ Python และ composite literal ของ Go editor ใส่ให้อัตโนมัติ
แล้วก็มีคนคัดลอก object literal จากไฟล์ .js ไปยังไฟล์ .json แล้วไฟล์นั้นก็ parse ไม่ได้อีก
อีกแหล่งที่พบบ่อยคือ JSON ที่สร้างด้วยมือ: loop ที่รันเงื่อนไข i <= length จะเหลือ comma ไว้หลังสมาชิกตัวสุดท้าย
วิธีแก้สามแบบ
ลบคอมมาออก ใช้ได้ดีกับการแก้ด้วยมือ วางลงใน formatter JSON แล้ว error จะถูกรายงานพร้อมบรรทัดและคอลัมน์ คุณจะเห็นได้ชัดว่าต้องลบตัวไหน
parse เป็น JSON5 superset รับ trailing comma ได้ ซึ่งใช้ได้กับ config ในเครื่อง แต่ไม่ใช้ได้กับอะไรก็ตามที่ส่งไปยังระบบอื่น — ปลายทางก็ยังปฏิเสธอยู่ดี
เลิกต่อ string ใช้ JSON.stringify, json.dumps, Jackson serializer จัดการตัวคั่นได้ถูกต้องและแก้เรื่อง escaping ไปพร้อมกัน
รายการตรวจเร็ว
| จุดที่เกิด | สาเหตุทั่วไป |
|---|---|
| การต่อ string ใน loop | i <= length ทำให้เหลือ comma เกินมาหนึ่งตัว |
| การคัดลอกวาง | object literal ที่ยกมาจากไฟล์ JS |
| template | comma ที่ hardcode ไว้บวก loop ที่เพิ่มอีกตัว |
| แก้ด้วยมือ | ลบฟิลด์สุดท้ายแล้วทิ้ง comma ของมันไว้ |
คำถามที่พบบ่อย
ทำไม trailing comma ถูกกฎใน JavaScript แต่ไม่ใน JSON?
object literal ของ JavaScript อนุญาตมาตั้งแต่ ES5 เช่นเดียวกับ list ของ Python และ composite literal ของ Go นี่คือเหตุผลที่นิสัยนี้ติดตามคนเข้าไปใน JSON RFC 8259 อนุญาต comma เฉพาะระหว่างสมาชิก: สมาชิกตัวสุดท้ายตามด้วย } หรือ ] ตรง ๆ การคัดลอก object literal จากไฟล์ .js ไปยังไฟล์ .json คือแหล่งที่พบบ่อย
ควร parse เป็น JSON5 เพื่อรับ trailing comma ไหม?
เฉพาะ config ในเครื่อง superset รับ trailing comma ได้ แต่สิ่งที่ส่งไปยังระบบอื่นจะถูก parse เป็น JSON เข้มงวดและยังล้มเหลวอยู่ ให้สร้าง JSON มาตรฐานที่ขอบของการส่งออกแทนการหวังให้ปลายทางผ่อนปรน
หลังเจอ error trailing comma ควรดูตรงไหนก่อน?
เริ่มจากตำแหน่งในข้อความ error: มักชี้ที่ comma ก่อน } หรือ ] จากนั้นตรวจแหล่งที่พบบ่อยสามแห่ง: loop ที่เขียนด้วย i <= length, object literal ที่วางมาจากไฟล์ JS และ template ที่ hardcode comma ไว้ข้าง loop การวางลงใน formatter จะรายงานบรรทัดและคอลัมน์ให้แม่นยำ