前端说接口返回的不是 JSON,fetch 里 res.json() 直接抛错。打开 Network 看响应头,Content-Type 是 text/html,因为文件末尾多了一个空行,前面还带着 BOM。

三行发一个标准响应

<?php header('Content-Type: application/json; charset=utf-8'); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit;

charset 写上,中文才不至于在某些客户端里变乱码。JSON_UNESCAPED_UNICODE 让中文按原样输出,调试时肉眼可读,体积也比转义后小一点。

header 之前不能有任何输出

包括 BOM、空格、换行,甚至 include 进来的文件末尾多出的空行。报 headers already sent 时,警告信息会指出输出是从哪个文件的第几行开始的,顺着找基本都能定位。

  • 编辑器里把 PHP 文件存成 UTF-8 无 BOM。
  • 纯 PHP 文件结尾不写闭合标记,能省掉一类莫名其妙的空行。
  • 调试用的 echo、var_dump 记得删干净再上线。

编码失败要能看见原因

json_encode 碰到非法 UTF-8 会返回 false,页面直接空白,很难查。加一层判断,把错误信息带出来,比盯着白屏猜要快。

$json = json_encode($data, JSON_UNESCAPED_UNICODE); if ($json === false) { http_response_code(500); echo json_encode(['error' => json_last_error_msg()]); exit; } echo $json;

跨域请求还要补上 Access-Control-Allow-Origin,预检的 OPTIONS 请求单独返回 204。否则前端看到的是跨域报错,跟 JSON 本身没关系。