Node.js调用Gemini Pro Vision AI API遇「Invalid JSON response: null」错误求助
问题:调用Gemini Pro Vision AI API时返回「Invalid JSON response: null」错误
我在Node.js应用中使用Gemini Pro Vision AI API,基于提示词生成文本,但向/speech端点发送请求时,收到「Invalid JSON response: null」错误。
已完成以下排查:
- 验证API密钥正确
- 通过Postman测试端点,响应正常
- 检查服务端代码的JSON序列化无错误
附上前后端代码,寻求调试帮助:
前端代码
async function sendPrompt(file, prompt, language) { try { const datasend = { file, prompt, language }; const jsonData = JSON.stringify(datasend); const response = await fetch("/speech", { method: "POST", headers: { "Content-Type": "application/json" }, body: jsonData }); if (response.ok) { const contentType = response.headers.get("content-type"); if (contentType && contentType.includes("application/json")) { const data = await response.json(); const text = data.text; // const image = data.file; // Speak the text using the p5.js library speech.speak(text); // Redirect naar de pagina met de image URL // window.location.href = `/generate-prompt?imageUrl=${encodeURIComponent( // JSON.stringify(image) + "?imageUrl=" ${encodeURIComponent(JSON.stringify(text))} // )}`; console.log("Upload response:", data); } else { console.warn("Unexpected response format. Not JSON."); } } else { console.error("Failed to upload photo:", response.statusText); } console.log("Upload response:", data); } catch (err) { console.log(err); } }
后端代码
app.post("/speech", async (req, res) => { const prompt = req.body.prompt; const file = req.body.file; const language = req.body.language; console.log(prompt, file, language); if (prompt) { const userId = await getUserIdFromSession(req.session); // Call the new function console.log("userId", userId); const options = { method: "POST", url: "https://gemini-pro-vision-ai1.p.rapidapi.com/", headers: { "content-type": "application/json", "X-RapidAPI-Key": "71956f59b5msh089630402391f02p108b9bjsna7adb689e8c4", "X-RapidAPI-Host": "gemini-pro-vision-ai1.p.rapidapi.com" }, data: { contents: [ { parts: [ { inline_data: { mime_type: "image/png", data: "https://www.takeaway.com/be/foodwiki/uploads/sites/2/2017/10/doner-kebab-3-1080x960.jpg" } }, { text: "gedraag je als een hulp assistent voor een blind persoon" + prompt + "in de volgende taal" + language } ] } ] } }; try { const response = await axios.request(options); const jsonData = response.data; if (jsonData && jsonData.candidates && jsonData.candidates.length > 0) { const text = jsonData.candidates[0].content.parts[0].text; console.log(text); // Log de volledige respons await savePrompt(prompt, file, language, userId, text); res.json({ text, file }); } else { console.error("Invalid JSON response:", jsonData); // Mogelijk moet hier een fallback-logica worden toegevoegd } } catch (error) { console.error(error); } } });
调试与修复方案
1. 后端未返回异常响应导致前端解析失败
当前后端代码存在两个核心问题:
- 当API返回的
jsonData结构不符合预期时,仅打印错误但未向前端返回任何响应,导致前端请求超时或收到空内容,解析JSON时出现null错误。 - catch块捕获到API请求异常时,仅打印错误但未向前端返回错误响应,前端同样会收到空响应。
修复后的后端代码:
app.post("/speech", async (req, res) => { const prompt = req.body.prompt; const file = req.body.file; const language = req.body.language; console.log(prompt, file, language); if (!prompt) { return res.status(400).json({ error: "Prompt参数不能为空" }); } try { const userId = await getUserIdFromSession(req.session); console.log("userId", userId); const options = { method: "POST", url: "https://gemini-pro-vision-ai1.p.rapidapi.com/", headers: { "content-type": "application/json", "X-RapidAPI-Key": "71956f59b5msh089630402391f02p108b9bjsna7adb689e8c4", "X-RapidAPI-Host": "gemini-pro-vision-ai1.p.rapidapi.com" }, data: { contents: [ { parts: [ { inline_data: { mime_type: "image/png", data: file // 替换硬编码URL为前端传入的file参数(需确保file是base64格式) } }, { text: "gedraag je als een hulp assistent voor een blind persoon " + prompt + " in de volgende taal " + language } ] } ] } }; const response = await axios.request(options); const jsonData = response.data; if (jsonData && jsonData.candidates && jsonData.candidates.length > 0) { const text = jsonData.candidates[0].content.parts[0].text; console.log(text); await savePrompt(prompt, file, language, userId, text); res.json({ text, file }); } else { const errorMsg = "AI API返回无效响应结构"; console.error(errorMsg, jsonData); res.status(500).json({ error: errorMsg, details: jsonData }); } } catch (error) { console.error("AI API请求失败:", error); res.status(500).json({ error: "服务端请求AI接口失败", details: error.message }); } });
2. 前端潜在问题修复
- 前端中
console.log("Upload response:", data);位于if(response.ok)块外部,此时data可能未定义,需移到块内。 - 如果
file是文件对象,JSON.stringify无法正确序列化,需先将文件转为base64格式再发送(匹配API的inline_data.data参数要求)。
修复后的前端代码片段:
async function sendPrompt(file, prompt, language) { try { // 将文件对象转为base64字符串(仅当API要求传入base64时使用) const fileData = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result.split(',')[1]); reader.onerror = reject; reader.readAsDataURL(file); }); const datasend = { file: fileData, prompt, language }; const jsonData = JSON.stringify(datasend); const response = await fetch("/speech", { method: "POST", headers: { "Content-Type": "application/json" }, body: jsonData }); if (response.ok) { const contentType = response.headers.get("content-type"); if (contentType && contentType.includes("application/json")) { const data = await response.json(); if (data.error) { console.error("服务端错误:", data.error); return; } const text = data.text; speech.speak(text); console.log("Upload response:", data); } else { console.warn("Unexpected response format. Not JSON."); } } else { const errorData = await response.json().catch(() => null); console.error("Failed to upload photo:", errorData?.error || response.statusText); } } catch (err) { console.log(err); } }
3. 额外优化点
- 拼接提示文本时添加空格,避免出现单词连写(比如
persoonpromptin),影响AI理解。 - 确认前端传入的
file格式与API要求一致(当前API的inline_data.data需要base64字符串,若API支持URL则需调整参数逻辑)。
内容的提问来源于stack exchange,提问作者giovanni p
相关产品推荐
相关产品推荐

