Cara membetulkan kesilapan hurai JSON: menyemak Unexpected token langkah demi langkah
Inti pati: Tukar kesilapan JSON.parse kepada baris dan aksara, kemudian hapuskan enam punca: koma hujung, petikan tunggal, komen, aksara kawalan, BOM dan pemotongan.

Kesimpulan utama: apabila berlaku kesilapan hurai, baca baris dan lajur yang dilaporkan untuk mencari aksara tidak sah pertama, kemudian tentukan sama ada ia petikan yang hilang, koma yang hilang, koma hujung, BOM, atau pemotongan — jangan baca semula keseluruhan dokumen dari permulaan.
Mesej kesilapan tidak pernah memberitahu anda "apa yang salah"; ia hanya memberitahu anda "di mana penghurai tidak dapat meneruskan". Kedua-dua kedudukan itu selalunya bukan tempat yang sama.
1. Pertama, terjemahkan kesilapan itu kepada koordinat
JSON rosak yang sama menghasilkan kesilapan yang sangat berbeza dalam bahasa yang berbeza, tetapi semuanya boleh ditukar menjadi "baris mana, aksara mana":
| Persekitaran | Kesilapan lazim | Cara membacanya |
|---|---|---|
| Pelayar / Node | Unexpected token } in JSON at position 42 |
position ialah offset aksara berasaskan 0, bukan nombor baris |
| Node 20+ | Unexpected non-whitespace character after JSON at position 42 |
bermaksud bahagian pertama sah dan kandungan tambahan bermula selepas 42 |
| Java Jackson | Unexpected character ('}' (code 125)): was expecting ... at [Source: (String)..."..." ; line: 3, column: 1] |
memberikan baris dan lajur secara terus, paling boleh digunakan antara semua |
| Python | json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 1 (char 42) |
char ialah offset; baris dan lajur yang penting |
| Go | invalid character '}' looking for beginning of object key string |
hanya memberikan aksara, jadi anda perlu menjejak ke belakang dan mencarinya sendiri |
Sebaik sahaja anda mempunyai kedudukan itu, tampal JSON ke dalam penghurai JSON dalam talian; alat itu meletakkan kursor pada lokasi kesilapan dan menyerlahkan nombor baris serta lajur — langkah ini menjimatkan 90% daripada memerhati aksara dengan mata.
2. Enam kesilapan berfrekuensi tinggi
1. Koma hujung
{
"name": "json",
"version": 1,
}
Terdapat koma berlebihan sebelum }. Spesifikasi JSON tidak membenarkan koma hujung, manakala literal objek JavaScript membenarkannya, jadi konfigurasi yang disalin daripada kod paling berkemungkinan membawanya. Pembetulan: padam koma terakhir; jika data ini sememangnya berada dalam fail JS sejak awal, beralih kepada penukaran JSON5 dan jangan paksakan ia menjadi JSON.
2. Petikan tunggal dan kunci tanpa petikan
{ 'name': 'json' }
{ name: "json" }
Rentetan JSON hanya boleh menggunakan tanda petikan berganda, dan kunci juga mesti rentetan berpetikan berganda. Kedua-dua ini ialah sintaks longgar JSON5 / JavaScript, bukan JSON. Tanda petikan berganda di dalam rentetan mesti ditulis sebagai \", dan garis miring terbalik sebagai \\.
3. Komen
{
// Timeout in milliseconds
"timeout": 3000
}
Tatabahasa RFC 8259 tidak mempunyai tempat untuk komen. Sama ada padam komen itu, atau simpan sebagai .jsonc / .json5 dan gunakan penghurai yang menyokong komen. Untuk pertukaran antara pelbagai "skema komen", lihat Cara menulis komen dalam JSON.
4. Baris baharu mentah dan aksara kawalan di dalam rentetan
{"sql": "SELECT *
FROM t"}
Rentetan JSON tidak boleh mengandungi suapan baris mentah, tab, atau aksara kawalan U+0000–U+001F; ia mesti ditulis sebagai \n, \t, \u0009. Apabila memasukkan teks berbilang baris ke dalam JSON, escape-kannya sekali dalam editor dahulu, atau kendalikannya secara seragam dengan Minify dan escape JSON.
5. Pengepala BOM
UTF-8 yang disimpan oleh Notepad Windows membawa tiga bait EF BB BF. JSON.parse melaporkan Unexpected token apabila menemui BOM, dan mata tidak dapat melihatnya sama sekali. Cara mengenal pasti: periksa pengepala fail dalam hex, atau salin kandungan ke alat dalam talian dan lihat sama ada aksara pertama dipaparkan sebagai . Pembetulan: simpan sebagai "UTF-8 tanpa BOM".
6. Kandungan terpotong
Log yang hanya mencetak 4096 aksara pertama, respons API yang terputus oleh gateway, muat turun yang terganggu — ciri khas kelas ini ialah "kesilapan berada di hujung" dan kiraan kurungan tidak sepadan. Kira kurungan dahulu: jika penutup { dan [ tidak sepadan, ia adalah pemotongan, bukan kesilapan sintaks. Dalam kes itu jangan betulkan apa-apa — pergilah mendapatkan data yang lengkap.
3. Dua penggera palsu berkaitan teks Cina dan escape
Cina bertukar menjadi \u4e2d\u6587: ini escaping JSON yang sah, bukan teks rosak. Selepas dihurai, nilai itu dipulihkan kepada Cina; bentuk \u hanya muncul apabila anda melihat rentetan mentah secara terus. Apabila anda perlu menunjukkannya kepada orang, hanya outputkannya dengan alat pemformatan; anda hanya perlu mempedulikan strategi escaping apabila Cina mesti bertahan dalam URL atau log.
Cina bertukar menjadi teks rosak seperti 涓枃: ini masalah pengekodan, bukan masalah JSON. Ia berlaku apabila bait UTF-8 dinyahkod sebagai GBK, menghasilkan corak tetap "tiga aksara mewakili satu aksara Cina". Semak Content-Type: application/json; charset=utf-8 pada pengepala respons, dan semak sama ada encoding='utf-8' dinyatakan secara eksplisit semasa membaca fail.
4. Aliran kerja pembaikan lima minit
- Tampal ke dalam alat: gunakan penghurai dalam talian dahulu untuk mencari kesilapan pertama, dan betulkan satu demi satu sahaja;
- Sahkan selepas setiap pembetulan: hurai semula selepas setiap perubahan, supaya membetulkan beberapa tempat sekali gus tidak membiarkan kesilapan baharu menutupi yang lama;
- Minify sekali: buang ruang putih dengan Minify dan hurai semula; ini membezakan "kesilapan struktur" daripada "masalah ruang putih atau baris baharu";
- Bandingkan struktur: jika kesilapan tiba-tiba muncul selepas perubahan, gunakan diff JSON terhadap versi sebelumnya; perbezaannya biasanya satu koma itu;
- Pengesahan peringkat medan: jika sintaks lulus tetapi lapisan perniagaan menolaknya (medan hilang, jenis salah), itu tergolong dalam pengesahan JSON Schema, bukan masalah sintaks.
5. Mengapa satu daripada dua petikan JSON "yang kelihatan serupa" dihurai dan satu lagi tidak
Punca paling lazim ialah aksara tidak kelihatan: koma lebar penuh ,, tanda petikan lebar penuh “”, ruang tidak putus U+00A0, ruang lebar sifar U+200B. Di skrin ia hampir tidak dapat dibezakan daripada pasangan separuh lebarnya, tetapi tiada satu pun daripadanya menjadi sebahagian daripada tatabahasa JSON.
Hanya ada satu cara untuk mengetahuinya: salin kandungan di sekitar aksara yang menjadi masalah dan periksa titik kod bait demi bait. Menjalankan yang berikut dalam konsol pelayar menyenaraikan setiap aksara yang bukan ASCII dan di luar julat Cina:
[...text].filter((ch) => {
const code = ch.codePointAt(0);
return code > 127 && !(code >= 0x4e00 && code <= 0x9fff);
});
Jika 0x201c (petikan berganda kiri), 0xff0c (koma lebar penuh), atau 0x00a0 muncul dalam output, itulah penyebabnya.
6. Pencegahan lebih murah daripada pembaikan
- Jalankan semakan hurai pada fail konfigurasi sebelum melakukan commit; satu baris dalam CI sudah cukup:
node -e "JSON.parse(require('fs').readFileSync('config.json','utf8'))"; - Jana respons API dengan pustaka penyerialan; jangan sekali-kali menggabungkan rentetan dengan tangan — rentetan yang dibina dengan tangan ialah satu-satunya punca koma hujung dan petikan yang hilang;
- Apabila melog JSON, panggil
JSON.stringifydahulu dan jangan menyisipkannya ke dalam templat, supaya muatan yang separuh ditulis tidak disalah anggap sebagai mesej lengkap.
Soalan Lazim
Bagaimana saya mencari kedudukan kesilapan sintaks JSON dengan pantas?
Ambil kedudukan atau baris/lajur yang dilaporkan oleh penghurai; position ialah offset aksara berasaskan 0, bukan nombor baris, manakala Java Jackson dan Python melaporkan baris dan lajur secara terus. Tampal JSON ke dalam penghurai JSON dalam talian dan alat itu meletakkan kursor pada lokasi kesilapan dan menyerlahkan baris serta lajur. Jika kesilapan berada di permulaan, semak pengepala fail untuk BOM dan cari aksara tidak kelihatan.
Mengapa konfigurasi yang disalin daripada kod begitu mudah membawa koma hujung?
Spesifikasi JSON melarang koma hujung manakala literal objek JavaScript membenarkannya, jadi konfigurasi yang disalin daripada kod JS mudah membawanya bersama. Pembetulannya hanya memadam koma terakhir; jika data itu sememangnya tergolong dalam fail JS, beralih kepada penukaran JSON5 lebih sesuai daripada memaksakannya menjadi JSON.
Bolehkah saya menghurai fail konfigurasi yang mengandungi komen sebagai JSON biasa?
Tidak — tatabahasa RFC 8259 tidak mempunyai tempat untuk komen, jadi menghuraikannya secara terus menimbulkan kesilapan. Sama ada padam komen itu, atau simpan sebagai .jsonc / .json5 dan gunakan penghurai yang menyokong komen. Untuk pertukaran antara skema komen, lihat Cara menulis komen dalam JSON.