Unexpected token < in JSON at position 0 的錯誤解析
輸出檢查一下便知
Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0
當你傳送一個HTTP請求,可能是用Fetch或者其他的Ajax庫,可能會出現這個錯誤提示,或者相似的錯誤。
接下來我將解釋這是由什麼引起的,我們應該怎樣解決這些問題
1.引起的原因
這些錯誤發生在當你向伺服器傳送請求,返回值不是JSON而用JSON的方法解析的時候,發生這種情況的程式碼可能是這樣的。
fetch('/users').then(res => res.json())
實際的請求沒有問題,它得到了一個返回值,發生問題的關鍵在於res.json()
2. JSON.parse
用另一種方法JSON.parse
來解析Json的, 程式碼可能是這樣的
JSON.parse(`不是Json的字串`);
JSON.parse()
本質上是和res.json()
一樣的,所以它們發生錯誤的情況是相同的。
3. 無效的JSON
JSON應該以有效的JSON值開始 —— 一個object, array, string, number, 或者是
false/true/null。以<
開始的返回值會有Unexpected token <
這樣的提示。
<
這個符號意味著返回值是HTML而不是JSON。
引起這個錯誤的根源是服務端返回的是HTML或者其他不是Json的字串。
為什麼會這樣呢?
“Unexpected token o in JSON at position 1” 或者其他變數。
錯誤的提示一些差別會隨著伺服器返回的不同而不同
它所提示的符號或者位置可能不同,但是引起它的原因是相同的: 你的程式碼所有解析的Json不是真的有效的Json。
下面是一些我所看見的錯誤的提示:
Unexpected token < in JSON at position 1
Unexpected token p in JSON at position 0
Unexpected token d in JSON at position 0
4.解決方案
With fetch, you can use res.text() instead of res.json() to get the text string itself. Alter your code to read something like this, and check the console to see what’s causing the problem:
首先要做是先把返回值打印出來。如果用fetch,可以用res.text()
res.json()
來獲得字串。把你的程式碼轉換成如下這樣,並且通過打印出來的內容檢視哪裡出問題了。
fetch('/users')
// .then(res => res.json()) // comment this out for now
.then(res => res.text()) // convert to plain text
.then(text => console.log(text)) // then log it out
注意像res.json()
和res.text()
這樣的方法是非同步的。所以不能直接把它們的返回值打印出來,這就是console.log必須在.then的括號裡面的原因。
5. 是因為伺服器的原因嗎?
伺服器有好幾種原因返回HTML而不是JSON:
- 請求的url不存在,伺服器以HTML的方式返回404頁面。你可能在請求時程式碼寫錯(像把/user寫成了/users),或者服務端的程式碼的錯誤。
- 當添加了新的路由時,伺服器需要重啟。比如你在用Express寫的伺服器時,剛剛新加了一個
app.get('/users', ...)
路由,但是沒有重啟,伺服器就不會對新的路由地址有反應。 - 客戶端的代理沒有設定: 如果在使用像Create React App的Webpack dev server時,你可以設定一個指向後端伺服器的代理。
- API的根url是
/
,如果你在通過Webpack 或Create React App使用代理,要確認你的API路由不在根的層級/
。這樣會時代理伺服器混淆,你將得到一個HTML而不是你的API請求的返回。你可以在如有前面加個字首像/api/
。
同時可以通過devtools的network檢視請求的返回值。
是不是404頁面?(可能是缺少該地址或者程式碼輸入錯誤)。
這是不是index.html的頁面?(可能是缺少地址或者代理配置錯誤)
如果一切看起來沒問題(新加的地址,服務端沒有重啟),那就重啟前端和後端伺服器,看看是不是問題解決了