JSON Toolkit

วิธีแก้ JSON parse error: ตรวจ Unexpected token ทีละขั้น

สรุปสำคัญ: แปลง error ของ JSON.parse ให้เป็นบรรทัดและตัวอักษร แล้วตัดสาเหตุหกประการออกไป: เครื่องหมายจุลภาคท้ายรายการ เครื่องหมายคำพูดเดี่ยว คอมเมนต์ อักขระควบคุม BOM และการตัดทอนข้อมูล

ผู้เริ่มต้นอ่านประมาณ 12 นาทีเผยแพร่ 2026-10-30อัปเดต 2026-11-01
ภาพหน้าปกการวินิจฉัย JSON parse error

สรุปสั้น: เมื่อเกิด parse error ให้อ่านบรรทัดและคอลัมน์ที่รายงานเพื่อหาอักขระผิดกฎตัวแรก แล้วตัดสินว่าเป็นเครื่องหมายคำพูดที่ขาด เครื่องหมายจุลภาคที่ขาด เครื่องหมายจุลภาคท้ายรายการ BOM หรือการตัดทอนข้อมูล — อย่าอ่านเอกสารใหม่ทั้งหมดตั้งแต่ต้น

ข้อความ error ไม่เคยบอกว่า "อะไรผิด" มันบอกแค่ว่า "ตัวแยกวิเคราะห์ไปต่อไม่ได้ที่ไหน" สองตำแหน่งนี้มักไม่ใช่ที่เดียวกัน

1. แปลง error เป็นพิกัดก่อน

JSON ที่พังแบบเดียวกันให้ error ต่างกันโดยสิ้นเชิงในแต่ละภาษา แต่ทั้งหมดแปลงเป็น "บรรทัดไหน ตัวอักษรตัวไหน" ได้:

สภาพแวดล้อม error ที่พบบ่อย วิธีอ่าน
เบราว์เซอร์ / Node Unexpected token } in JSON at position 42 position คือ character offset เริ่มนับที่ 0 ไม่ใช่เลขบรรทัด
Node 20+ Unexpected non-whitespace character after JSON at position 42 หมายถึงส่วนแรกถูกต้อง และเนื้อหาเกินเริ่มหลังตำแหน่ง 42
Java Jackson Unexpected character ('}' (code 125)): was expecting ... at [Source: (String)..."..." ; line: 3, column: 1] ให้บรรทัดและคอลัมน์โดยตรง ใช้งานได้ดีที่สุด
Python json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 1 (char 42) char คือ offset; บรรทัดและคอลัมน์คือสิ่งที่สำคัญ
Go invalid character '}' looking for beginning of object key string ให้เฉพาะอักขระ ต้องย้อนกลับไปหาตำแหน่งเอง

เมื่อได้ตำแหน่งแล้ว ให้วาง JSON ลงใน ตัวแยกวิเคราะห์ JSON ออนไลน์; เครื่องมือจะวางเคอร์เซอร์ที่ตำแหน่ง error และไฮไลต์เลขบรรทัดและคอลัมน์ — ขั้นตอนนี้ประหยัดเวลาไล่ดูอักขระได้ 90%

2. หก error ที่พบบ่อย

1. เครื่องหมายจุลภาคท้ายรายการ

{
  "name": "json",
  "version": 1,
}

มีเครื่องหมายจุลภาคเกินมาก่อน } ข้อกำหนด JSON ไม่อนุญาตเครื่องหมายจุลภาคท้ายรายการ ขณะที่ object literal ของ JavaScript อนุญาต คอนฟิกที่คัดลอกจากโค้ดจึงมีโอกาสพามาด้วยมากที่สุด วิธีแก้: ลบเครื่องหมายจุลภาคตัวสุดท้าย; ถ้าข้อมูลนี้อยู่ในไฟล์ JS ตั้งแต่แรก ให้เปลี่ยนไปใช้ การแปลง JSON5 ดีกว่าฝืนให้เป็น JSON

2. เครื่องหมายคำพูดเดี่ยวและคีย์ที่ไม่ครอบเครื่องหมายคำพูด

{ 'name': 'json' }
{ name: "json" }

สตริง JSON ใช้ได้เฉพาะเครื่องหมายคำพูดคู่ และคีย์ก็ต้องเป็นสตริงที่ครอบเครื่องหมายคำพูดคู่เช่นกัน สองแบบนี้เป็นไวยากรณ์แบบผ่อนปรนของ JSON5 / JavaScript ไม่ใช่ JSON เครื่องหมายคำพูดคู่ภายในสตริงต้องเขียนเป็น \" และแบ็กสแลชเป็น \\

3. คอมเมนต์

{
  // Timeout in milliseconds
  "timeout": 3000
}

ไวยากรณ์ของ RFC 8259 ไม่มีที่ให้คอมเมนต์ ให้ลบคอมเมนต์ออก หรือบันทึกเป็น .jsonc / .json5 แล้วใช้ตัวแยกวิเคราะห์ที่รองรับคอมเมนต์ สำหรับข้อแลกเปลี่ยนของ "วิธีใส่คอมเมนต์" แบบต่าง ๆ ดู วิธีเขียนคอมเมนต์ใน JSON

4. การขึ้นบรรทัดใหม่และอักขระควบคุมดิบภายในสตริง

{"sql": "SELECT *
FROM t"}

สตริง JSON บรรจุ line feed, แท็บ หรืออักขระควบคุม U+0000–U+001F แบบดิบไม่ได้ ต้องเขียนเป็น \n, \t, \u0009 เมื่อต้องยัดข้อความหลายบรรทัดลงใน JSON ให้ escape ในเอดิเตอร์ก่อนครั้งหนึ่ง หรือจัดการอย่างสม่ำเสมอด้วย บีบอัดและ escape JSON

5. ส่วนหัว BOM

UTF-8 ที่บันทึกโดย Notepad ของ Windows พาไบต์สามตัว EF BB BF มาด้วย JSON.parse รายงาน Unexpected token เมื่อเจอ BOM และสายตามองไม่เห็นเลย วิธีตรวจ: ดูส่วนหัวไฟล์ในรูป hex หรือคัดลอกเนื้อหาไปยังเครื่องมือออนไลน์แล้วดูว่าอักขระแรกแสดงเป็น  หรือไม่ วิธีแก้: บันทึกเป็น "UTF-8 without BOM"

6. เนื้อหาถูกตัดทอน

log ที่พิมพ์เพียง 4096 ตัวอักษรแรก response ของ API ที่ถูก gateway ตัด การดาวน์โหลดที่ถูกขัดจังหวะ — ลายเฉพาะของกลุ่มนี้คือ "error อยู่ที่ท้าย" และจำนวนวงเล็บไม่ตรงกัน ให้นับวงเล็บก่อน: ถ้าวงเล็บปิดของ { และ [ ไม่ตรงกัน แสดงว่าถูกตัดทอน ไม่ใช่ syntax error ในกรณีนั้นอย่าแก้ไขอะไร — ไปเอาข้อมูลฉบับเต็มมา

3. สองการเตือนที่หลอกเรื่องข้อความจีนและการ escape

ข้อความจีนกลายเป็น \u4e2d\u6587: นี่คือการ escape ของ JSON ที่ถูกต้อง ไม่ใช่ตัวขยะ หลังแยกวิเคราะห์ ค่าจะกลับมาเป็นภาษาจีน; รูปแบบ \u จะแสดงก็ต่อเมื่อคุณดูสตริงดิบโดยตรง เมื่อต้องแสดงให้คนเห็น ก็แค่ส่งออกด้วย เครื่องมือจัดรูปแบบ; คุณต้องสนใจกลยุทธ์การ escape ก็ต่อเมื่อภาษาจีนต้องอยู่รอดใน URL หรือ log

ข้อความจีนกลายเป็นตัวขยะอย่าง 涓枃: นี่คือปัญหาการเข้ารหัส ไม่ใช่ปัญหาของ JSON เกิดเมื่อไบต์ UTF-8 ถูกถอดรหัสเป็น GBK ได้ผลลัพธ์เป็นรูปแบบ "สามตัวอักษรแทนหนึ่งอักขระจีน" นี้ ตรวจส่วนหัวของ response ว่าเป็น Content-Type: application/json; charset=utf-8 และตรวจว่าได้ระบุ encoding='utf-8' อย่างชัดเจนตอนอ่านไฟล์หรือไม่

4. ขั้นตอนการซ่อมภายในห้านาที

  1. วางลงในเครื่องมือ: ใช้ ตัวแยกวิเคราะห์ออนไลน์ หา error ตัวแรกก่อน และแก้ทีละจุดเท่านั้น;
  2. ตรวจสอบหลังแก้ทุกครั้ง: แยกวิเคราะห์ใหม่ทุกครั้งที่เปลี่ยน เพื่อไม่ให้การแก้หลายจุดพร้อมกันทำให้ error ใหม่กลบ error เก่า;
  3. บีบอัดหนึ่งครั้ง: ตัดช่องว่างด้วย Minify แล้วแยกวิเคราะห์ใหม่; ขั้นนี้แยก "error เชิงโครงสร้าง" ออกจาก "ปัญหาช่องว่างหรือการขึ้นบรรทัดใหม่";
  4. เปรียบเทียบโครงสร้าง: ถ้า error โผล่ขึ้นมาหลังการเปลี่ยนแปลง ให้ใช้ JSON diff เทียบกับเวอร์ชันก่อนหน้า; ความต่างมักเป็นเครื่องหมายจุลภาคตัวเดียว;
  5. ตรวจระดับฟิลด์: ถ้าไวยากรณ์ผ่านแต่ชั้นธุรกิจปฏิเสธ (ฟิลด์หาย ชนิดผิด) นั่นเป็นเรื่องของ JSON Schema validation ไม่ใช่ปัญหาทางไวยากรณ์

5. ทำไม JSON สองชิ้นที่ "หน้าตาเหมือนกัน" แยกวิเคราะห์ผ่านชิ้นเดียว

สาเหตุที่พบมากที่สุดคือ อักขระที่มองไม่เห็น: เครื่องหมายจุลภาคแบบเต็มความกว้าง , เครื่องหมายคำพูดแบบเต็มความกว้าง “” ช่องว่างแบบไม่ตัดบรรทัด U+00A0 และช่องว่างความกว้างศูนย์ U+200B บนหน้าจอแทบแยกไม่ออกจากตัวครึ่งความกว้าง แต่ไม่มีตัวใดเป็นส่วนหนึ่งของไวยากรณ์ JSON

มีวิธีเดียวที่จะรู้: คัดลอกเนื้อหารอบ ๆ อักขระที่มีปัญหาแล้วดู code point ทีละไบต์ การรันต่อไปนี้ในคอนโซลเบราว์เซอร์จะแสดงอักขระทุกตัวที่ไม่ใช่ ASCII และอยู่นอกช่วงภาษาจีน:

[...text].filter((ch) => {
  const code = ch.codePointAt(0);
  return code > 127 && !(code >= 0x4e00 && code <= 0x9fff);
});

ถ้า 0x201c (เครื่องหมายคำพูดคู่ซ้าย), 0xff0c (เครื่องหมายจุลภาคเต็มความกว้าง) หรือ 0x00a0 โผล่ในเอาต์พุต แสดงว่าตัวนั้นคือต้นเหตุ

6. การป้องกันถูกกว่าการซ่อม

  • รันการตรวจ parse กับไฟล์คอนฟิกก่อนคอมมิต บรรทัดเดียวใน CI ก็พอ: node -e "JSON.parse(require('fs').readFileSync('config.json','utf8'))";
  • สร้าง response ของ API ด้วยไลบรารีทำให้เป็นอนุกรม ห้ามต่อสตริงด้วยมือ — สตริงที่ประกอบด้วยมือเป็นต้นเหตุเดียวของเครื่องหมายจุลภาคท้ายรายการและเครื่องหมายคำพูดที่ขาด;
  • เมื่อบันทึก log ของ JSON ให้เรียก JSON.stringify ก่อน อย่าแทรกเข้าไปในเทมเพลต เพื่อไม่ให้ payload ที่เขียนค้างครึ่งทางถูกเข้าใจผิดว่าเป็นข้อความที่สมบูรณ์

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

จะหาตำแหน่งของ JSON syntax error ได้เร็วอย่างไร

ใช้ตำแหน่งหรือบรรทัด/คอลัมน์ที่ตัวแยกวิเคราะห์รายงาน; position คือ character offset เริ่มนับที่ 0 ไม่ใช่เลขบรรทัด ขณะที่ Java Jackson และ Python รายงานบรรทัดและคอลัมน์โดยตรง วาง JSON ลงใน ตัวแยกวิเคราะห์ JSON ออนไลน์ แล้วเครื่องมือจะวางเคอร์เซอร์ที่ตำแหน่ง error และไฮไลต์บรรทัดและคอลัมน์ ถ้า error อยู่ที่จุดเริ่มต้น ให้ตรวจส่วนหัวไฟล์ว่ามี BOM และมองหาอักขระที่มองไม่เห็น

ทำไมคอนฟิกที่คัดลอกจากโค้ดจึงมีโอกาสพาเครื่องหมายจุลภาคท้ายรายการมาด้วย

ข้อกำหนด JSON ห้ามเครื่องหมายจุลภาคท้ายรายการ ขณะที่ object literal ของ JavaScript อนุญาต คอนฟิกที่คัดลอกมาจากโค้ด JS จึงพามาได้ง่าย วิธีแก้ก็แค่ลบเครื่องหมายจุลภาคตัวสุดท้าย; ถ้าข้อมูลอยู่ในไฟล์ JS อยู่แล้ว การเปลี่ยนไปใช้ การแปลง JSON5 เข้ากว่าการฝืนให้เป็น JSON

แยกวิเคราะห์ไฟล์คอนฟิกที่มีคอมเมนต์เป็น JSON ปกติได้ไหม

ไม่ได้ — ไวยากรณ์ของ RFC 8259 ไม่มีที่ให้คอมเมนต์ การแยกวิเคราะห์โดยตรงจึงเกิด error ให้ลบคอมเมนต์ออก หรือบันทึกเป็น .jsonc / .json5 แล้วใช้ตัวแยกวิเคราะห์ที่รองรับคอมเมนต์ สำหรับข้อแลกเปลี่ยนของวิธีใส่คอมเมนต์ ดู วิธีเขียนคอมเมนต์ใน JSON