如何正确抛出PHP自定义异常以返回数组格式响应?
问题:如何让CustomException抛出的message为合法JSON对象?
我现在有一段验证错误处理的代码:
$errors = $this->validator->validate($request); if (\count($errors) > 0) { $errorBag = ErrorMessageHelper::generateErrorMessage($errors); throw new CustomException(json_encode($errorBag), Response::HTTP_INTERNAL_SERVER_ERROR); }
这里的$errorBag是一个数组,抛出异常后,返回的响应格式是这样的:
"error":{"code":500,"message":"{\"postalCode\":\"This value should have exactly 7 characters.\"}"}
可以看到message是JSON编码后的字符串,而不是合法的JSON对象。我尝试过重写CustomException,但不仅没效果,还返回了空响应,求可行的解决思路。
解决思路与方案
兄弟,我之前也碰到过类似的问题,核心问题其实不是重写异常类本身,而是你的**全局异常处理器(或异常处理中间件)**在输出响应时的逻辑有问题。给你几个可行的方向:
1. 调整CustomException的设计,直接接收数组
别先把$errorBag转成JSON字符串再传给异常,直接把数组存到异常实例里,这样后续处理更灵活。修改CustomException的构造函数:
class CustomException extends \Exception { protected array $errorData; public function __construct(array $errorData, int $code = 0, \Throwable $previous = null) { // 这里的消息可以设为通用提示,或者留空,反正后续不用它 parent::__construct('Validation failed', $code, $previous); $this->errorData = $errorData; } // 提供获取错误数组的方法 public function getErrorData(): array { return $this->errorData; } }
然后抛出异常时直接传数组:
throw new CustomException($errorBag, Response::HTTP_INTERNAL_SERVER_ERROR);
2. 修复全局异常处理器的响应格式化逻辑
这才是关键!之前你重写异常类没用,大概率是因为全局异常处理的地方,还是把getMessage()的结果直接当成字符串塞到响应里了。以Laravel为例,找到App\Exceptions\Handler类,修改render方法:
public function render($request, Throwable $exception) { // 针对CustomException做特殊处理 if ($exception instanceof CustomException) { return response()->json([ 'error' => [ 'code' => $exception->getCode(), 'message' => $exception->getErrorData() // 直接传数组,框架自动转成JSON对象 ] ], $exception->getCode()); } // 其他异常交给默认处理逻辑 return parent::render($request, $exception); }
这样返回的响应里,message就是合法的JSON对象了,不会出现嵌套转义的问题。
3. 退而求其次:不修改异常类的方案
要是你暂时不想动CustomException的结构,那就在异常处理器里把message的JSON字符串解码成数组再输出:
public function render($request, Throwable $exception) { if ($exception instanceof CustomException) { // 解码JSON字符串 $errorMessage = json_decode($exception->getMessage(), true); // 加个判断,避免解码失败导致的错误 if (json_last_error() !== JSON_ERROR_NONE) { $errorMessage = $exception->getMessage(); } return response()->json([ 'error' => [ 'code' => $exception->getCode(), 'message' => $errorMessage ] ], $exception->getCode()); } return parent::render($request, $exception); }
总结
核心逻辑就是:让响应生成时直接接收数组类型的错误数据,框架的json()方法会自动把数组转换成合法的JSON对象;如果先把数组转成JSON字符串再塞进去,只会导致响应里的message变成转义后的字符串,这就是你之前遇到的问题。
内容的提问来源于stack exchange,提问作者Suraj Gusain
相关产品推荐
相关产品推荐

