应直接使用jsonresponse类返回json响应,它自动设置content-type、utf-8编码并安全处理null等值;避免手写json_encode()+response或传入未处理的doctrine实体;需统一监听kernel.exception处理api异常并校验accept头;cors推荐使用nelmio/cors-bundle配置。

直接用 JsonResponse 类返回,别手写 json_encode() + Response。它自动设好 Content-Type: application/json、UTF-8 编码,还安全处理 null、NaN 等边缘值。
正确创建 JSON 响应
在控制器中引入并实例化:
use Symfony\Component\HttpFoundation\JsonResponse;
return new JsonResponse($data);
-
$data可以是数组、标量、实现JsonSerializable的对象 - 要指定 HTTP 状态码,传第二个参数:
new JsonResponse($data, 400) - 避免传入资源句柄、闭包、未处理的 Doctrine 实体——会触发序列化异常
安全序列化 Doctrine 实体
实体不能直接塞进 JsonResponse,否则容易因循环引用(如 User ↔ Post)崩溃或 N+1 查询。
- 最简方案:在实体中定义
toArray()方法,只返回基础字段 - 推荐方案:用 DTO 手动投影关键数据,解耦 API 层与数据库结构
- 慎用 Serializer:若必须用,需配
ObjectNormalizer+JsonEncoder,并设circular_reference_limit防栈溢出 - 禁用
get_object_vars():它会暴露私有属性和代理对象内部字段
统一处理 API 异常为 JSON
别在每个 action 里写 try-catch,用内核事件监听器集中转换。
- 监听
kernel.exception事件 - 仅对
Accept: application/json或 AJAX 请求做 JSON 转换,保留普通页面跳转逻辑 - 针对不同异常类型返回标准结构,例如:
['error' => 'access_denied', 'message' => '...'] - 状态码需匹配语义:400 对 validation 失败,401/403 对认证授权问题,500 仅用于未捕获错误
避免常见 JSON 安全陷阱
前端解析失败、响应内容被转义、状态码错乱,多数源于这几个细节:
- 不要用
Response::setContent(json_encode(...))—— 缺少Content-Type头,浏览器/客户端可能不识别为 JSON - 不要把已序列化的 JSON 字符串再包进
JsonResponse:new JsonResponse(['data' => $jsonString])会导致字符串被双重编码 - 确保响应体是合法 JSON 结构:数组应包在对象里(如
{"items": [...]}),而非裸数组[...](部分老客户端拒绝解析) - CORS 需显式配置:推荐用
nelmio/cors-bundle,精确控制Access-Control-Allow-Origin等头











