본문으로 건너뛰기
jsonbeautifiers
한국어
V8 Node v24.15.0, V8 13.6.233.17에서 파서를 실행해 확인했습니다.

"undefined" is not valid JSON

JSON.parse에 undefined를 넘겼습니다. 그것은 문자열 "undefined"로 바뀌고, JSON에는 그런 리터럴이 없어서 0번 위치에서 실패합니다. 진짜 질문은 그 undefined가 어디서 왔느냐이고, 답은 대략 셋뿐입니다.

이렇게 적힌 것을 보게 될 수도 있습니다

  • Unexpected token u in JSON at position 0

V8은 2022년에 JSON 오류 메시지 대부분을 다시 썼습니다. 검색 결과에 나오는 건 여전히 옛 문구가 대부분이지만, 지금의 어떤 런타임도 그 문구를 내보내지 않습니다.

JSON을 붙여넣고 어디서 깨지는지 정확히 확인하기

입력

붙여 넣은 것은 여러분의 브라우저를 떠나지 않습니다. connect-src 허용 목록 덕분에 이는 약속이 아니라 브라우저가 강제하는 보장입니다. 직접 확인하기

실제 원인

어느 쪽이 답인 경우가 많은지, 그 순서대로 정리했습니다.

  1. 01 한 번도 설정된 적 없는 스토리지 키

    localStorage.getItem은 없는 키에 대해 null을 돌려주고, JSON.parse(null)은 실제로 동작합니다. 하지만 그 키에 문자열 "undefined"가 한 번이라도 기록됐다면, 다시 읽을 때마다 정확히 이 오류가 납니다. 키를 지울 때까지 계속입니다.

    깨지는 예

    localStorage.setItem('token', someUndefinedValue);   // writes "undefined"
    JSON.parse(localStorage.getItem('token'));

    되는 예

    const raw = localStorage.getItem('token');
    const token = raw && raw !== 'undefined' ? JSON.parse(raw) : null;
  2. 02 비동기 값을 기다리지 않음

    프로미스에서, 또는 아직 로드되지 않은 상태에서 속성을 읽으면 undefined가 됩니다. 데이터가 도착하기 전에 파싱이 실행된 것입니다.

    깨지는 예

    const data = JSON.parse(fetchUser().body);

    되는 예

    const res = await fetchUser();
    const data = JSON.parse(await res.text());
  3. 03 존재하지 않는 속성

    이름이 바뀐 필드, 오타, 또는 형태가 달라진 API. 페이로드가 obj.result를 쓰는데 obj.data를 읽으면 다른 경고 하나 없이 undefined가 나옵니다.

자주 묻는 질문

왜 JSON.parse(null)은 되는데 JSON.parse(undefined)는 안 되나요?
둘 다 먼저 문자열로 바뀝니다. null은 "null"이 되는데 이건 유효한 JSON 문서라 파싱되어 null을 돌려줍니다. undefined는 "undefined"가 되고, JSON에는 그에 해당하는 리터럴이 없습니다.
문자열 "undefined"가 든 키는 어떻게 지우나요?
localStorage.removeItem(키)를 쓰거나, 위에 보인 것처럼 읽는 쪽을 방어하세요. 잘못된 값은 새로고침을 넘겨서도 남기 때문에, 이 오류는 기기마다 나타났다 안 났다 하는 것처럼 보이곤 합니다.

지금 고치기

위의 도구에 페이로드를 붙여넣거나, 이 일을 위해 만들어진 도구로 바로 가세요.

페이로드 검증하기