Next.js 13客户端调用API路由报错:返回HTML而非有效JSON
问题排查:Next.js 13客户端组件调用API路由解析JSON失败
问题场景
使用Next.js 13作为后端框架、React作为前端框架,从客户端组件调用API路由获取JSON数据时,控制台能看到服务器返回JSON,但客户端抛出错误:Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON"
核心原因及解决方案
1. API路由写法不符合Next.js 13 App Router规范
Next.js 13的App Router中,API路由必须通过export async function GET(而非默认导出函数)的方式定义,且参数获取逻辑和旧版Pages Router不同:
- 路径参数(如
id)需从第二个参数的params属性中获取 - 查询参数(如
size、style)需通过request.nextUrl.searchParams获取
修正后的API路由代码:
import db from "../../../../utils/db"; import Product from "../../../../models/Product"; import { NextResponse } from "next/server"; // 采用App Router要求的导出方式 export async function GET(request, { params }) { try { await db.connectDb(); const { id } = params; // 正确获取路径参数 const searchParams = request.nextUrl.searchParams; const size = searchParams.get('size'); const style = searchParams.get('style'); const product = await Product.findById(id).lean(); if (!product) { return NextResponse.json({ message: "产品不存在" }, { status: 404 }); } const subProduct = product.subProducts[style]; if (!subProduct) { return NextResponse.json({ message: "款式不存在" }, { status: 404 }); } const sizeData = subProduct.sizes[size]; if (!sizeData) { return NextResponse.json({ message: "尺寸不存在" }, { status: 404 }); } let discount = subProduct.discount; let priceBefore = sizeData.price; let price = discount ? priceBefore - priceBefore / discount : priceBefore; await db.disconnectDb(); return NextResponse.json({ _id: product._id, style: Number(style), name: product.name, description: product.description, slug: product.slug, sku: subProduct.sku, brand: product.brand, category: product.category, subCategories: product.subCategories, shipping: product.shipping, images: subProduct.images, color: subProduct.color, size: sizeData.size, price, priceBefore, quantity: sizeData.qty, }); } catch (error) { console.error(error); return NextResponse.json( { message: error.message }, { status: 500 } ); } }
2. API路由文件结构错误
Next.js 13 App Router的API路由必须放在app/api/[路由路径]/route.js路径下。例如,如果你的API路径是/api/product/[id],则文件必须命名为app/api/product/[id]/route.js,否则Next.js会返回HTML格式的404页面,导致JSON解析失败。
3. 客户端请求路径优化
客户端请求时建议使用相对路径,避免硬编码http://localhost:3000,方便后续部署:
async function handleClick() { const response = await fetch(`/api/product/${product._id}?style=${product.style}&size=${dsize}`, { method: "GET", headers: { "Content-Type": "application/json", Accept: "application/json", }, }); const data = await response.json(); console.log(data); }
内容的提问来源于stack exchange,提问作者Deezy
相关产品推荐
相关产品推荐

