NaN หรือ Infinity ปรากฏใน JSON ได้ไหม
สรุปสำคัญ: JSON มีเฉพาะ literal ของตัวเลขฐานสิบเท่านั้น JSON.stringify เปลี่ยน NaN และ Infinity เป็น null โดยไม่เตือน นี่คือเหตุผลที่ "ฟิลด์ตัวเลขบางครั้งเป็น null" ยังโผล่ใน production

สรุปสั้น ๆ: JSON แทนค่า NaN หรือ Infinity ไม่ได้ — JSON.stringify เปลี่ยนทั้งสองเป็น null อย่างเงียบ ๆ — ดังนั้นให้เข้ารหัสสถานะอย่างชัดเจนด้วย null พร้อมฟิลด์เหตุผล หรือใช้ค่า string ที่ระบุไว้ในเอกสาร
JSON.stringify({ ratio: NaN, limit: Infinity });
// '{"ratio":null,"limit":null}'
ไม่มี error ไม่มีคำเตือน ตัวเลขสองตัวกลายเป็น null
ไวยากรณ์อนุญาตอะไร
number = [ minus ] int [ frac ] [ exp ]
ฐานสิบเท่านั้น NaN และ Infinity เป็น sentinel ของ IEEE 754 ไม่ใช่ literal เมื่อเขียนลง JSON มันเป็น identifier ที่ไม่ถูกต้อง และเนื่องจากความหมายของการเปรียบเทียบต่างกันไปในแต่ละภาษา มาตรฐานจึงตัดมันออกแทนที่จะเลือกตัวแทนสักแบบ
แต่ละภาษาทำอะไรแทน
| ภาษา | พฤติกรรม |
|---|---|
JSON.stringify ของ JavaScript |
ส่งออก null อย่างเงียบ ๆ |
json.dumps ของ Python |
ส่งออก NaN โดยค่าเริ่มต้น (ไม่เป็นมาตรฐาน); throw เมื่อ allow_nan=False |
encoding/json ของ Go |
คืน unsupported value: NaN |
| Jackson ของ Java | ส่งออก string "NaN" โดยค่าเริ่มต้น |
ค่าหนึ่งค่าแต่พฤติกรรมสี่แบบ เมื่อ API ข้ามภาษาแสดงฟิลด์ตัวเลขที่เป็น null เป็นครั้งคราว ให้ตรวจชั้นนี้ก่อน
ควรทำอะไรแทน
ใช้ string ที่ระบุในเอกสาร "NaN", "Infinity" พร้อมหมายเหตุเรื่องชนิด ต้นทุนคือผู้ใช้ทุกคนต้องตรวจอย่างชัดเจน
ใช้ null พร้อมฟิลด์สถานะ ดีกว่า: {"avgLatency": null, "avgLatencyStatus": "no-sample"} เหตุผลไปกับค่าตัวเลข
ทบทวนหน่วย ผลลัพธ์ Infinity ส่วนใหญ่มาจากการหารด้วยตัวอย่างที่เป็นศูนย์ การคืน null แล้วแสดง "ยังไม่มีข้อมูล" มักตรงกับความจริงทางธุรกิจมากกว่าตัวเลขอนันต์
กับดักที่เกี่ยวข้อง
- ไลบรารีกราฟจะขาดเส้นที่
null— ยืนยันว่านั่นคือสิ่งที่คุณต้องการ JSON.stringifyยังตัดundefined, function และ symbol ออกทั้งหมด; key เหล่านั้นหายไปเลยแทนที่จะกลายเป็นnull- ค่าเริ่มต้น
allow_nan=Trueของ Python ให้ output ที่JSON.parseปฏิเสธ