JSON Toolkit

ทำไมภาษาจีนกลายเป็น \u4e2d\u6587

สรุปสำคัญ: การ escape แบบ \u4e2d\u6587 เป็น Unicode ที่ถูกกฎ ไม่ใช่การเข้ารหัสล้มเหลว ตัวอักษรเพี้ยนจริงหน้าตาต่างออกไป และการแยกแยะสองกรณีนี้ตัดสินว่าคุณต้องแก้อะไรจริง ๆ

ผู้เริ่มต้นอ่านประมาณ 3 นาทีเผยแพร่ 2026-10-30อัปเดต 2026-10-30
การ escape Unicode กับการเพี้ยนของอักขระจริงใน JSON

สรุปสั้น ๆ: ถือว่า output \uXXXX เป็นการ escape ที่ถูกกฎ ตรวจว่า round-trip ผ่าน JSON.parse แล้ว และปิดการ serialize แบบ ASCII ล้วนอย่าง ensure_ascii=False เมื่อต้องการเห็นภาษาจีนที่อ่านได้; เก็บการ escape ไว้เฉพาะช่องทางที่ไม่สามารถบรรทุกอักขระที่ไม่ใช่ ASCII

เพราะมันถูก escape ไม่ได้เสียหาย

JSON.parse('"\\u4e2d\\u6587"')  // "中文"

\u4e2d คือ 中 และ \u6587 คือ 文 ทั้งสองเป็น escape sequence ที่ถูกกฎ parser ใด ๆ คืนค่ากลับให้ ไม่มีอะไรพัง — แค่อ่านไม่ได้ใน log, diff และไฟล์ packet capture

ใครเป็นคน escape

เครื่องมือ ค่าเริ่มต้น วิธีปิด
json.dumps ของ Python escape (ensure_ascii=True) ensure_ascii=False
JSON.stringify ของ JavaScript ไม่ escape —
Jackson ของ Java ไม่ escape ไม่บังคับ
json_encode ของ PHP ไม่ escape ตั้งแต่ 5.4 —
encoding/json ของ Go ไม่ escape —

Python เป็นแหล่งที่พบบ่อยที่สุด ค่าเริ่มต้นมีเหตุผลของมัน: output ASCII ล้วนอยู่รอดได้ทุกช่องทาง ต้นทุนคืออักขระที่ไม่ใช่ ASCII ทุกตัวกลายเป็นหกอักขระ

การ escape กับอักขระเพี้ยน

การ escape: \u4e2d\u6587 ตรงกับรูปแบบ \uXXXX เกิดจากการตั้งค่า serializer อักขระเพี้ยน: 测试, 涓枃 เกิดจากการเขียนไบต์ UTF-8 แล้วอ่านเป็น Latin-1 หรือ GBK

ทดสอบเร็ว ๆ: วางข้อความลงใน browser console เป็น JSON.parse('"…"') ถ้าคืนค่าออกมาอ่านได้ แสดงว่าเป็นการ escape ถ้าล้มเหลวหรือยังเพี้ยนอยู่ แสดงว่าการเข้ารหัสไม่ตรงกัน — และวิธีแก้คือทำการเข้ารหัสให้ตรงกัน ไม่ใช่ไปแก้ serializer

ปิดมัน

json.dumps(data, ensure_ascii=False)

จากนั้นตรวจปลายทาง: ระบบเก่าบางตัวพึ่งพาการขนส่งแบบ ASCII ล้วนจริง ๆ โดยเฉพาะ SMS gateway และ mail relay รุ่นเก่า

เมื่อไรการ escape จึงเป็นทางเลือกที่ถูก

  • ช่องทางที่เป็นปฏิปักษ์กับอักขระที่ไม่ใช่ ASCII (HTTP header รุ่นเก่า, SMS gateway บางตัว)
  • JSON ที่ซ้อนอยู่ใน string ของ JSON อีกชั้น ซึ่งการ escape ลดการชนกันของเครื่องหมายคำพูด
  • pipeline ของ log ที่ตัดตามไบต์และจะผ่าอักขระหลายไบต์

นอกนั้นให้เลือกความอ่านง่ายและปิดมัน

คำถามที่พบบ่อย

ทำไม Python ถึง escape ภาษาจีนโดยค่าเริ่มต้น?

เพราะ ensure_ascii=True เป็นค่าเริ่มต้น ซึ่งรับประกัน output ASCII ล้วนที่อยู่รอดได้ทุกช่องทาง ต้นทุนคืออักขระที่ไม่ใช่ ASCII ทุกตัวกลายเป็นหกอักขระ

ควรปิด ensure_ascii ไหม?

ปิดเมื่อความอ่านง่ายสำคัญ จากนั้นตรวจปลายทาง — HTTP header รุ่นเก่า, SMS gateway บางตัว และ pipeline ของ log ที่ตัดตามไบต์อาจยังพึ่งเนื้อหา ASCII ล้วน

ถ้าช่องทางบรรทุกอักขระที่ไม่ใช่ ASCII ไม่ได้จะเกิดอะไรขึ้น?

ให้เก็บการ escape ไว้ เมื่อ JSON ถูกฝังใน string ของ JSON อีกชั้น หรือเดินทางผ่านช่องทางที่เป็นปฏิปักษ์กับอักขระที่ไม่ใช่ ASCII การ escape ช่วยเลี่ยงการชนกันของเครื่องหมายคำพูดและป้องกันอักขระหลายไบต์ถูกผ่า

อ่านเพิ่มเติม