我怎样才能在friendsofsymfony / rest-bundle v3中以json格式显示所有错误

问题描述

在将它们显示为JSON之后,我想拦截Symfony的所有错误。 在friendsofsymfony / rest-bundle v2中,我可以设置参数

fos_rest:
    exception:
        enabled: true
         exception_controller: 'App\Controller\ExceptionController::showAction'
    ...

但是在V3中,参数exception_controller被删除了。

我当前的FOS REST配置:

fos_rest:
  view:
    formats:
      xml:  false
      json: true
    view_response_listener: force
  serializer:
    groups: ['Default']
    serialize_null: true
  format_listener:
    rules:
      - { path: ^/api/v1,priorities: [ json ],fallback_format: json,prefer_extension: true }
  exception:
    enabled: true

官方手册说应该在JMS中使用处理程序。 https://symfony.com/doc/current/bundles/FOSRestBundle/4-exception-controller-support.html 但这并没有说明如何在yaml中设置配置。

解决方法

您可以拦截symfony订阅者的所有错误

<?php

declare(strict_types=1);

namespace App\Util\Serializer\Normalizer;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

class CustomExceptionHandler implements SubscribingHandlerInterface
{
    private bool $debug;

    public function __construct(bool $kernelDebug)
    {
        $this->debug = $kernelDebug;
    }

    public static function getSubscribingMethods(): array
    {
        return [
            [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,'format'    => JsonEncoder::FORMAT,'type'      => \Exception::class,'method'    => 'serializeToJson','priority'  => -1,],];
    }

    public function serializeToJson(
        JsonSerializationVisitor $visitor,\Exception $exception,array $type,Context $context
    ) {
        $data = $this->convertToArray($exception,$context);

        return $visitor->visitArray($data,$type);
    }

    /**
     * @return array<string,mixed>
     */
    protected function convertToArray(\Exception $exception,Context $context): array
    {
        $statusCode = null;

        if ($context->hasAttribute('template_data')) {
            $templateData = $context->getAttribute('template_data');

            if (array_key_exists('status_code',$templateData)) {
                $statusCode = $templateData['status_code'];
            }
        }

        $data['error'] = $this->getMessageFromThrowable($exception,$statusCode);

        return $data;
    }

    protected function getMessageFromThrowable(\Throwable $throwable,?int $statusCode): string
    {
        if ($this->debug) {
            return $throwable->getMessage();
        }

        return array_key_exists($statusCode,Response::$statusTexts) ? Response::$statusTexts[$statusCode] : 'error';
    }
}

services.yaml

 App\Utils\Serializer\Normalizer\CustomExceptionHandler:
     $kernelDebug: '%kernel.debug%'

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...