JSON Toolkit

ค้นหาข้อความ error ของ JSON: จากข้อความ error สู่การแก้ไขทันที

สรุปสำคัญ: ค้นหาสาเหตุจากข้อความ JSON.parse แบบตรงตัว: error ที่พบบ่อย 12 แบบใน Chrome, Firefox และ Safari รวมถึงหน้า error แบบ HTML การตัดทอนข้อมูล และการแยกวิเคราะห์ซ้ำ

ขั้นสูงอ่านประมาณ 8 นาทีเผยแพร่ 2026-10-30อัปเดต 2026-11-04
ภาพหน้าปกตารางค้นหาข้อความ error ของ JSON

สรุปสั้น: เมื่อเกิด error จาก JSON.parse ให้จับตำแหน่งและ token ก่อน; ตำแหน่งเป็น 0 หมายถึงต้องตรวจว่าได้ response เป็น HTML, มี BOM หรือชนิดข้อมูลผิด ส่วนข้อความ "Expected" หมายถึงต้องดูอักขระตัวก่อนหน้า — ห้ามเริ่มอ่านไล่ทีละบรรทัดจากตำแหน่งที่รายงาน

ข้อความ error ไม่ใช่เสียงรบกวน — มันคือคำตอบ ตัวแยกวิเคราะห์บอกคุณว่าชนอักขระตัวไหน คาดหวังอะไร และได้รับอะไรจริง การค้นด้วยข้อความ error ได้ผลกว่าการเขียนเอกสารใหม่ทั้งไฟล์ด้วยมือ

ทุก error ของ JSON.parse() มีสามส่วน: ตำแหน่ง (character offset หรือบรรทัด/คอลัมน์), สิ่งที่คาดหวัง (Expected...) และ ความจริง (Unexpected token X หรือ xxx is not valid JSON) แต่ละเอนจินใช้ถ้อยคำต่างกัน — Chrome และ Node (V8) พูดว่า Expected ',' or '}' after property value in JSON at position 25 Firefox พูดว่า JSON.parse: expected ',' or '}' after property value in object at line 3 column 1 Safari พูดว่า JSON Parse error: Expected ',' or '}' — แต่ทั้งสามชี้ไปที่จุดแตกหักทางไวยากรณ์เดียวกัน เมื่อค้นหา error ให้เพิกเฉยต่อถ้อยคำแล้วจับข้อเท็จจริงสามอย่าง: อักขระตัวไหน คาดหวังอะไร และอะไรมาถึง

1. ตารางค้นหา error 12 แบบ

คอลัมน์ซ้ายคือส่วนที่ระบุตัวตนได้ชัดที่สุดจากคอนโซลของคุณ (ถ้อยคำของ V8) ตัวแปรของ Firefox/Safari อยู่ในวงเล็บ

ข้อความ error (V8) สาเหตุจริง วิธีแก้
Unexpected token < in JSON at position 0 API ตอบกลับเป็น HTML (หน้า 404 เทมเพลต 500 การเปลี่ยนเส้นทางไปหน้า login หรือ fallback ของพร็อกซี) ไม่ใช่ JSON ตรวจ response.status และ Content-Type ก่อน อย่าไปแก้ JSON
Unexpected end of JSON input ข้อมูลว่างหรือถูกตัดทอน: body ว่าง 204 การดาวน์โหลดถูกขัดจังหวะ การคัดลอกตกบรรทัดสุดท้าย จัดการกรณีว่าง เปรียบเทียบ Content-Length เพื่อหาจุดตัด
Unexpected token o / "[object Object]" is not valid JSON object ที่แยกวิเคราะห์แล้วถูกส่งเข้า JSON.parse() อีกครั้งและถูกแปลงเป็นสตริง ตรวจ typeof; ถ้าเป็น object ให้ใช้ค่านั้นโดยตรง
"undefined" is not valid JSON ตัวแปรไม่เคยถูกกำหนดค่า (JSON.parse(undefined)) กำหนดค่าเริ่มต้นสำรอง และตรวจสอบก่อนแยกวิเคราะห์
Expected double-quoted property name in JSON มีเครื่องหมายจุลภาคท้ายรายการ ({"a": 1,}) ตัวแยกวิเคราะห์คาดว่าจะมีคีย์อีกตัวแต่กลับเจอ } ลบเครื่องหมายจุลภาคหลังรายการสุดท้าย
Expected property name or '}' in JSON คีย์ที่ไม่ครอบเครื่องหมายคำพูด หรือใช้เครื่องหมายคำพูดเดี่ยว ({name: "Ada"}, {'name': 'Ada'}) ครอบทุกคีย์ด้วยเครื่องหมายคำพูดคู่
Expected ',' or '}' after property value in JSON ขาดเครื่องหมายจุลภาค ({"a": 1 "b": 2}) หรือมีคอมเมนต์หลังค่า เติมเครื่องหมายจุลภาค; ลบคอมเมนต์
Unexpected token '/' มีคอมเมนต์ // หรือ /* */ ภายใน JSON ลบออก หรือแยกวิเคราะห์ไฟล์ config เป็น JSONC
Bad control character in string literal มีการขึ้นบรรทัดใหม่ แท็บ หรืออักขระควบคุม U+0000–U+001F ดิบอยู่ภายในสตริง เขียนเป็น \n; สร้างด้วย JSON.stringify
Unterminated string in JSON สตริงเปิดด้วย " แล้วไม่ปิด หรือเครื่องหมายคำพูดภายในไม่ได้ escape escape เครื่องหมายคำพูดภายในเป็น \"
Unexpected non-whitespace character after JSON มีเอกสารสองชิ้นในข้อความเดียว: {}{}, NDJSON หรือตัวห่อ JSONP แยกตามบรรทัดแล้วแยกวิเคราะห์ทีละชิ้น หรือใช้ตัวแยกวิเคราะห์ NDJSON
JSON.parse is not a function ตัวแปรของคุณบัง JSON ส่วนกลางอยู่ เปลี่ยนชื่อตัวแปร; ห้ามตั้งชื่อว่า JSON

สองรายการแรกควรดูให้ละเอียด เพราะทั้งคู่ไม่ได้หมายความว่า "JSON ของคุณผิด" แต่หมายความว่า "สิ่งที่คุณได้รับไม่ใช่สิ่งที่คุณคิด"

2. ต้นเหตุที่พบบ่อยสามประการของ error ที่ตำแหน่ง 0

ตำแหน่งเป็น 0 หมายถึงอักขระตัวแรกสุดผิดกฎ ถ้าไม่มีอะไรดูน่าสงสัย อักขระนั้นน่าจะมองไม่เห็น ผู้ต้องสงสัยสามราย:

หนึ่ง: < หมายถึง HTML. นี่คือ parse error ที่พบมากที่สุดในการใช้งานจริง URL ผิด เซสชันหมดอายุแล้วถูก gateway เปลี่ยนเส้นทาง หรือเทมเพลตหน้า error ของเซิร์ฟเวอร์ — body เริ่มด้วย <!DOCTYPE html> และตัวแยกวิเคราะห์ก็หยุดที่อักขระตัวแรก สิ่งที่ควรทำคือเปิดแผง Network แล้วอ่าน response ดิบ จากนั้นแก้การเรียก API ไม่ใช่แก้ JSON

สอง: BOM หรืออักขระความกว้างศูนย์. ไฟล์ที่บันทึกด้วย Notepad ของ Windows มักเริ่มด้วย UTF-8 BOM (\uFEFF) และข้อความที่คัดลอกจากเว็บเพจหรือแอปแชทอาจพา zero-width space (\u200B–\u200D) มาด้วย คุณมองไม่เห็น แต่ตัวแยกวิเคราะห์เห็นชัด:

// Strip BOM and zero-width characters before parsing
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);

สาม: ชนิดข้อมูลผิด. JSON.parse(undefined) รายงาน "undefined" is not valid JSON; JSON.parse(someObject) รายงาน Unexpected token o (object ถูกแปลงเป็น "[object Object]" และ o ผิดกฎที่ตำแหน่ง 1) ทั้งคู่หมายความว่า "ข้อมูลถูกแยกวิเคราะห์แล้ว" หรือ "ไม่เคยมีข้อมูลเลย" ให้ตรวจชนิดข้อมูล ไม่ใช่ไวยากรณ์:

let data = text;
if (typeof data === 'string') {
  data = JSON.parse(data); // Parse only when it really is a string
}

3. ตำแหน่งชี้ไปทางปลายน้ำ แต่สาเหตุอยู่ต้นน้ำ

มี error สองแบบที่ทำให้เข้าใจตำแหน่งผิด และเป็นสองรายการในตารางที่คนอ่านพลาดมากที่สุด:

  • ขาดเครื่องหมายจุลภาค: {"a": 1 "b": 2} รายงาน Expected ',' or '}' after property value ที่บรรทัดของ "b" รายงานถูกต้อง แต่จุดที่ต้องแก้อยู่ท้ายบรรทัดก่อนหน้า
  • ขาดวงเล็บปิด: การซ้อนลึกที่ขาด } หรือ ] ไปหนึ่งตัวทำให้ตัวแยกวิเคราะห์กลืนทุกอย่างไปจนจบอินพุตแล้วรายงาน Unexpected end of JSON input ตำแหน่งคือท้ายไฟล์ แต่จุดที่ขาดจริงอาจอยู่ไกลก่อนหน้านั้นมาก ให้ค้นย้อนหลังหา { หรือ [ ที่ยังไม่ปิดล่าสุด — การนับคู่ได้ผลกว่าการกะด้วยสายตา

เทคนิคทั่วไปคือการแบ่งครึ่ง (bisection): ตัดข้อความก่อนตำแหน่งที่รายงานแล้วแยกวิเคราะห์เฉพาะส่วนนั้น ถ้าแยกวิเคราะห์ผ่าน ปัญหาอยู่ใกล้ตำแหน่งที่รายงาน; ถ้าไม่ผ่าน ให้แบ่งครึ่งย้อนกลับไปอีก ขอบเขตของส่วนแรกที่ล้มเหลวคือจุด error จริง สำหรับไฟล์ใหญ่ ให้จัดรูปแบบเอกสารก่อน — เมื่อการย่อหน้าเรียงตรงกัน ระดับที่ขาดหายจะเห็นได้ในพริบตา (ตัวจัดรูปแบบ JSON ออนไลน์ใช้ได้ดีในกรณีนี้)

4. สี่สถานะ "ดูปกติ" ที่แยกวิเคราะห์ผ่านแต่ทำงานผิด

ที่แย่กว่า error คือไม่มี error แต่ข้อมูลผิด ในทั้งสี่กรณี JSON ถูกต้องและตัวแยกวิเคราะห์พอใจ — ปัญหาคือรูปร่างของข้อมูล:

  1. เข้ารหัสซ้ำ (double encoding): เอกสารถูก JSON.stringify สองครั้ง ผลลัพธ์การแยกวิเคราะห์จึงเป็นสตริง ไม่ใช่ object ถ้า typeof result === 'string' ให้แยกวิเคราะห์อีกครั้ง — แต่ต้องหาและแก้การทำให้เป็นอนุกรมซ้ำที่ต้นทาง
  2. คีย์ซ้ำถูกเขียนทับอย่างเงียบ ๆ: {"name": "Tom", "name": "Jerry"} เป็น JSON ที่ถูกต้อง ตัวแยกวิเคราะห์ส่วนใหญ่ไม่บ่น และค่าที่สองชนะ ปัญหานี้จะกัดเมื่อรวมข้อมูลจากหลายแหล่ง ให้ตรวจด้วย ตัวตรวจสอบ JSON แบบเข้มงวดก่อนที่มันจะกัดคุณ
  3. NDJSON ถูกปฏิบัติเป็นเอกสารเดียว: API แบบสตรีมมิ่งส่ง object หนึ่งตัวต่อบรรทัด การแยกวิเคราะห์ทั้งข้อความจะล้มด้วย Unexpected non-whitespace character after JSON ให้แยกด้วย \n แล้วแยกวิเคราะห์ทีละบรรทัด
  4. สูญเสียความแม่นยำของตัวเลขอย่างเงียบ ๆ: จำนวนเต็มที่มากกว่า 2^53 - 1 (เช่น snowflake ID) จะได้ค่ากลับมาโดยหลักท้ายกลายเป็นศูนย์ โดยไม่มี error เลย ให้ส่ง ID เป็นสตริง

เส้นด้ายร่วม: ตัวแยกวิเคราะห์เชื่อว่าทุกอย่างเรียบร้อย ดังนั้นเมื่อข้อมูล API ดูผิด ให้พิมพ์ 80 ตัวอักษรแรกของข้อความดิบและ typeof ของมันก่อน — ยืนยันรูปร่างก่อน แล้วค่อยถกเถียงเรื่องเนื้อหา

5. ทำให้ error เป็นไปไม่ได้ตั้งแต่ตอนเขียน

ตารางค้นหาเป็นเครื่องมือแก้ไขย้อนหลัง ส่วนการป้องกันคือเครื่องมือก่อนเกิดเหตุ นิสัยสี่ข้อสกัดกั้น error ส่วนใหญ่ก่อนจะเกิด:

// 1. Two checks before parsing any response
const response = await fetch('/api/users');
if (!response.ok) {
  throw new Error(`HTTP ${response.status}: the API returned no data`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
  throw new Error(`Expected JSON, got ${contentType}`);
}
const data = await response.json(); // 2. json() already parses — do not parse again
  • สร้างด้วยการทำให้เป็นอนุกรม ไม่ใช่การต่อสตริง: JSON.stringify() จัดการเครื่องหมายคำพูด การขึ้นบรรทัดใหม่ และอักขระควบคุมได้ถูกต้อง; สตริงที่ประกอบด้วยมือคือต้นเหตุอันดับหนึ่งของ Bad control character และ Unterminated string
  • จับ error เสมอ: error ที่ถูก throw จาก JSON.parse จะทำให้โปรแกรมล่มแบบซิงโครนัสถ้าไม่มีอะไรจับ สำหรับอินพุตที่ไม่น่าไว้วางใจ — localStorage, ไฟล์ภายนอก — บล็อก catch ต้องมีค่าเริ่มต้นหรือรายงาน error อย่างชัดเจน
  • มอบหมายโครงสร้างให้ Schema: ไวยากรณ์ถูกต้องไม่ได้หมายความว่าโครงสร้างถูกต้อง ฟิลด์ที่หายไปและชนิดข้อมูลที่ผิดเป็นหน้าที่ของ JSON Schema validation ที่ขอบเขต; ดู JSON Schema แก้ปัญหาอะไร

6. เส้นทางการตัดสินใจแบบเร็ว

ย่อทั้งบทความให้เป็นลำดับการตัดสินใจเดียว เมื่อเจอ error ให้จับ ตำแหน่งและ token ก่อน:

  1. ตำแหน่ง 0 → ตรวจสามต้นเหตุ: < (HTML), BOM, ชนิดข้อมูลผิด;
  2. end of input → ตรวจว่า body ว่างหรือถูกตัดทอน แล้วค้นย้อนหลังหาวงเล็บที่ยังไม่ปิด;
  3. Expected ... → ดูอักขระตัวก่อนหน้า มักเป็นเครื่องหมายจุลภาคหรือเครื่องหมายคำพูดที่ขาด;
  4. after JSON data → มีเอกสารหลายชิ้นต่อกัน ให้แยกตามบรรทัด;
  5. แยกวิเคราะห์ผ่านแต่ข้อมูลดูผิด → ตรวจสี่สถานะ "ดูปกติ" ที่ทำงานผิด

เมื่อรวมกับขั้นตอนการวินิจฉัยใน วิธีแก้ JSON parse error ปัญหาการแยกวิเคราะห์ 90% แก้ได้ภายในห้านาที เก็บข้อความ error ไว้ในบุ๊กมาร์ก — มันคือ debug log ที่ตัวแยกวิเคราะห์เขียนให้คุณ ถ้อยคำเปลี่ยนทุกสามปี และการค้นครั้งเดียวคุ้มค่าหนึ่งปี

"Unexpected token in JSON" หมายความว่าอะไร

ตัวแยกวิเคราะห์ชนอักขระที่ผิดกฎ ณ จุดนั้นในไวยากรณ์ JSON token คืออักขระที่ถูกปฏิเสธ: < มักหมายถึง API ตอบ HTML, ' หมายถึงเครื่องหมายคำพูดเดี่ยว, / หมายถึงคอมเมนต์ และตัวอักษรธรรมดามักหมายถึงคีย์ที่ไม่ครอบเครื่องหมายคำพูด หรือค่าคงที่ที่ JavaScript เท่านั้นมีอย่าง undefined หรือ NaN ให้อ่าน token ก่อน แล้วจึงอ่านตำแหน่ง สาเหตุจะแคบลงเหลือหนึ่งอย่าง

จะแก้ "Unexpected end of JSON input" อย่างไร

มีสองต้นเหตุ: อินพุตว่าง (body ของ response ว่าง หรือสตริงว่างใน localStorage) หรืออินพุตถูกตัดทอน (ดาวน์โหลดถูกขัดจังหวะ การคัดลอกตกบรรทัดสุดท้าย ข้อจำกัดขนาด) จัดการกรณีว่างด้วย if (!text) return; จากนั้นตรวจความครบถ้วนและปิด {, [ หรือ " ที่ยังไม่ปิดล่าสุด สังเกตว่า error นี้เกิดจากวงเล็บที่ขาดหายลึก ๆ ได้ด้วย — ตำแหน่งบังเอิญอยู่ท้ายไฟล์

ทำไม Chrome, Firefox และ Safari รายงาน error ต่างกัน

ทั้งสามเบราว์เซอร์ใช้เอนจิน JS ต่างกัน (V8, SpiderMonkey, JavaScriptCore) และแต่ละตัวใช้ถ้อยคำของตน MDN บันทึกตัวแปรทางการทั้งหมดไว้ แต่ error ทั้งสามมีสามองค์ประกอบเดียวกัน — ตำแหน่ง สิ่งที่คาดหวัง ความจริง — ด้วยความหมายแบบหนึ่งต่อหนึ่ง ให้แปลเป็นถ้อยคำของ V8 แล้วใช้ตารางนี้ได้เลย

ตำแหน่ง error ชี้ไปยังจุดที่ดูปกติ — ต้องทำอย่างไรต่อ

error จริงอยู่ก่อนหน้านั้น กรณีทั่วไป: ขาดเครื่องหมายจุลภาค (ถูกรายงานในบรรทัดถัดไป) และขาดวงเล็บปิด (ถูกรายงานที่ท้ายไฟล์) ให้เดินย้อนหลังจากตำแหน่งที่รายงานทีละ token หรือแบ่งครึ่ง: แยกวิเคราะห์ครึ่งแรกเพียงลำพัง ขอบเขตของส่วนแรกที่ล้มเหลวคือจุด error ที่แท้จริง