使用LocalStorage中的Token发送POST请求时遭遇JSON构造无效错误的排查求助
排查LocalStorage获取Token发送POST请求返回「invalid json construct」的问题
问题描述
我在使用以下代码通过LocalStorage获取Token发送POST请求创建管理员时遇到异常:该请求在Postman和Hoppscotch中可正常执行,但代码运行时持续返回invalid json construct错误,响应内容为:{data: null, error: "invalid json construct", message: "", statuscode: 422}。
相关代码如下:
export const addAdmin = (values) => async (dispatch) => { var add = localStorage.getItem('user'); const res = await fetch('https://capitalluxurydev.xyz/v1/admin/createadmin', { method: 'POST', body: JSON.stringify(values), headers: { Authorization: add, 'Content-Type': 'application/json; charset=utf-8', }, credentials: 'same-origin', }); try { const data = await res.json(); console.log(data); return; } catch (error) { console.log(error); return; } };
可能的原因分析
- Authorization头格式错误:你直接把
localStorage.getItem('user')的结果放到Authorization头里,但user很可能是一个包含Token的完整用户对象JSON字符串,而非纯Token值。这种情况下,请求头的格式不符合后端预期,会干扰整个请求的解析流程,导致后端无法正确处理JSON请求体。 - 请求体JSON无效:如果
values对象中包含JSON.stringify无法序列化的内容(比如函数、Symbol类型、循环引用),生成的JSON字符串会损坏,后端解析时就会抛出「invalid json construct」错误。 - 跨域凭证配置不匹配:
credentials: 'same-origin'在跨域场景下会阻止凭证(比如Cookie)的传递,如果后端需要凭证才能正常解析请求,或者CORS配置不匹配,也可能间接引发这个问题。
解决方案
1. 修复Authorization头的Token格式
首先检查LocalStorage中user的实际内容:
console.log(localStorage.getItem('user'));
如果输出是类似{"token":"your-token-here", "username":"admin"}的JSON对象,需要先解析对象提取Token,并且注意很多后端要求Token前加上Bearer前缀:
// 修改获取Token的逻辑 const userStr = localStorage.getItem('user'); let token = ''; if (userStr) { try { const userObj = JSON.parse(userStr); token = userObj.token; // 根据实际字段名调整 } catch (parseErr) { console.error('解析LocalStorage用户数据失败:', parseErr); } } // 更新请求头 headers: { Authorization: token ? `Bearer ${token}` : '', // 没有Token时可以处理为空或抛出错误 'Content-Type': 'application/json; charset=utf-8', },
如果后端不需要Bearer前缀,直接传递token即可。
2. 确保请求体可正常序列化
在调用JSON.stringify(values)前先测试序列化是否正常,提前发现问题:
try { const testJson = JSON.stringify(values); console.log('序列化后的请求体:', testJson); } catch (serialErr) { console.error('请求体序列化失败:', serialErr); // 这里可以处理错误,比如过滤掉非可序列化的字段 }
如果发现序列化失败,需要清理values中的异常内容:
- 移除函数、Symbol类型的字段;
- 处理循环引用(可以使用第三方库如
flatted来序列化循环引用对象); - 如果
values包含文件,不能用JSON,需要改用FormData传递(同时后端要支持表单数据解析)。
3. 调整跨域凭证配置(跨域场景)
如果你的前端和后端部署在不同域名下,把credentials改为include:
credentials: 'include',
同时确保后端的CORS配置满足:
- 设置
Access-Control-Allow-Credentials: true; Access-Control-Allow-Origin指定为你的前端域名(不能是*)。
4. 优化错误捕获逻辑
把整个请求流程包裹在try/catch中,提前捕获解析Token、序列化请求体时的错误,方便排查:
export const addAdmin = (values) => async (dispatch) => { try { // 1. 处理Token const userStr = localStorage.getItem('user'); if (!userStr) { console.error('LocalStorage中无用户数据'); return; } const userObj = JSON.parse(userStr); const token = userObj.token; // 2. 序列化请求体 const serializedBody = JSON.stringify(values); // 3. 发送请求 const res = await fetch('https://capitalluxurydev.xyz/v1/admin/createadmin', { method: 'POST', body: serializedBody, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json; charset=utf-8', }, credentials: 'include', }); // 4. 处理响应 const data = await res.json(); console.log(data); // 这里添加dispatch的业务逻辑,比如dispatch(addAdminSuccess(data)) } catch (error) { console.error('请求处理出错:', error); // 处理错误,比如dispatch(addAdminFailure(error)) } };
内容的提问来源于stack exchange,提问作者Taiwo Sulaimon
相关产品推荐
相关产品推荐

