Czy BOM psuje parsowanie JSON
Podsumowanie: BOM UTF-8 to trzy niewidoczne bajty, więc JSON.parse zawodzi na pierwszym znaku i zgłasza wiersz 1 kolumnę 1, przez co plik wygląda na pusty lub obcięty.

Najważniejsze: sprawdź pierwsze trzy bajty pod kątem EF BB BF i zapisz ponownie jako UTF-8 bez BOM; na serwerze usuwaj wiodący U+FEFF przed parsowaniem jakiegokolwiek przesłanego lub zewnętrznego pliku, zamiast debugować awarię później.
Tak — i produkuje najbardziej mylący ze wszystkich błędów parsowania, bo plik wygląda całkowicie dobrze.
Co widzisz
SyntaxError: Unexpected token in JSON at position 0
Unexpected character '\uFEFF'
Ten znak w komunikacie jest niewidoczny. Position 0 oznacza pierwszy bajt.
cat nie pokazuje nic niezwykłego. hexdump -C file.json | head -1 pokazuje:
00000000 ef bb bf 7b 0a 20 20 22 61 22 3a 20 31 0a 7d 0a |...{ "a": 1.}.|
7b to {. Trzy bajty przed nim to BOM.
Skąd biorą się BOM-y
Byte order mark istniał dla UTF-16, gdzie kolejność bajtów naprawdę się różniła. UTF-8 ma jedną kolejność bajtów, więc BOM jest czystym narzutem — a mimo to Notatnik w Windows, część eksportów Excela i kilka starszych IDE nadal zapisuje go domyślnie.
RFC 8259 jest jednoznaczne: JSON wymieniany między systemami musi być UTF-8, a implementacje nie mogą dodawać BOM. Parsery mogą ignorować wiodący BOM, ale nie muszą. Przeglądarki i Node wybierają, że nie ignorują.
Trzy sposoby na pozbycie się go
Zapisz bez BOM. W VS Code kliknij kodowanie w pasku stanu i wybierz „Zapisz z kodowaniem → UTF-8”, a nie „UTF-8 z BOM”.
Usuń go z powłoki.
sed -i '1s/^\xEF\xBB\xBF//' data.json
Usuwaj przy odczycie. To trwała poprawka dla wszystkiego, co przyjmuje przesłane lub zewnętrzne pliki:
const text = require('node:fs').readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);
W Pythonie open(path, encoding='utf-8-sig') obsługuje to automatycznie.
Dwa podobne problemy
- Spacja zerowej szerokości (U+200B) — wychwytywana przy kopiowaniu JSON ze strony internetowej; identyczny objaw, inny punkt kodowy.
- Pełnoekranowe cudzysłowy — chiński IME zamienia
"key"na“key”, co wygląda niemal identycznie, ale zawodzi jakoUnexpected token “.
Wszystkie trzy to błędy niewidocznych znaków. Diagnostyka jest zawsze taka sama: zrzuć pierwsze bajty w systemie szesnastkowym, zamiast gapić się w tekst.
FAQ
Jak rozpoznać, czy plik zaczyna się od BOM?
cat nic nie pokazuje, więc uruchom hexdump -C file.json | head -1. Jeśli wyjście zaczyna się od ef bb bf, plik ma BOM; 7b (czyli {) powinno być pierwsze w czystym pliku UTF-8.
Dlaczego błąd zawsze wskazuje wiersz 1, kolumnę 1?
BOM siedzi przed wszystkim innym, więc pierwszym znakiem czytanym przez parser jest U+FEFF. Porażka ląduje więc na początku pliku, przez co plik wygląda na pusty.
Czy usuwać BOM przed parsowaniem?
Tak. Gdy serwer czyta konfigurację lub parsuje przesłane pliki, najpierw usuń wiodący U+FEFF — replace(/^\uFEFF/, '') w Node, encoding='utf-8-sig' w Pythonie — co jest znacznie tańsze niż diagnozowanie tego później.