You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 12:35:03