Ошибка сериализации с пакетом jms sirialize в Symfony

Я использую symfony 3 с пакетом сериализации jms. Как сериализовать исключение/ошибку с трассировкой стека в JSON для отправки клиенту? Скриншот исключения. введите здесь описание изображения

Помощник для генерации исключения:

namespace Bundle\DependencyInjection;
use Exception;

class UnknownException extends Exception
{
    public function __construct() {
        parent::__construct('An unknown exception occurred', 500, null);
    }
}

Я создаю исключение внутри контроллера:

$error= new UnknownException()

А потом отправляю:

$serializedError = $this->serializer->serialize( // it is jms serializer
    $error,
    'json'
);

$response = new Response();
$response
    ->setStatusCode($statusCode)
    ->setContent($serializedError)
    ->send();

Я получаю сообщение об ошибке на клиенте: Resources are not supported in serialized data

Я думаю, это происходит из-за того, что трассировка исключения представляет собой очень большую структуру: Пример скриншота трассировки исключения введите здесь описание изображения

Итак, как его сериализовать? Как сериализовать огромные структуры с помощью сериализатора jms?


person M.T.    schedule 01.06.2017    source источник
comment
Вы пытались аннотировать свое исключение какой-либо ExclusionPolicy?   -  person Igor Scabini    schedule 23.06.2017
comment
Нет, я этого не делал. Но ошибка Symfony по умолчанию имеет трассировку стека, которая выводится пользователю. Поэтому я вообще не хочу исключать трассировку стека, я хочу сериализовать ее для отправки клиенту в JSON. Спасибо! :)   -  person M.T.    schedule 20.07.2017


Ответы (1)


Наконец-то я нашел эту суть: https://gist.github.com/Thinkscape/805ba8b91cdce6bcaf7c и удается сериализовать исключения. Дело не в том, насколько они огромны или сложны, но некоторые поля не сериализуемы (например, замыкания или потоки).

Я помещаю свои исключения в содержащий класс и внутри этого класса хук предварительной сериализации:

class ErrorList
{
    /**
     * registrazione di eventuali errori
     *
     * @SWG\Property()
     *
     * @JMS\Type("ArrayCollection<ServiceCore\lib\exception\JsonableException>")
     *
     * @var ArrayCollection<ServiceCore\lib\exception\JsonableException>
     */
    protected $errors;

    /**
     * @JMS\PreSerialize
     */
    public function serialize()
    {
        foreach ($this->errors as $error) {
            JsonableException::flattenExceptionBacktrace($error);
        }
    }
}

в то время как JsonableException расширяет Exception функцией из gist:

class JsonableException extends \Exception
{

    public static function flattenExceptionBacktrace(\Exception $exception)
    {
         // file_put_contents("/tmp/dump.log", print_r(get_object_vars($this), true));
         $traceProperty = (new \ReflectionClass('Exception'))->getProperty('trace');
         $traceProperty->setAccessible(true);

         $flatten = function (&$value, $key) {
            if ($value instanceof \Closure) {
                $closureReflection = new \ReflectionFunction($value);
                $value = sprintf(
                    '(Closure at %s:%s)',
                    $closureReflection->getFileName(),
                    $closureReflection->getStartLine()
                );
            } elseif (is_object($value)) {
                $value = sprintf('object(%s)', get_class($value));
            } elseif (is_resource($value)) {
                $value = sprintf('resource(%s)', get_resource_type($value));
            }
         };

        do {
            $trace = $traceProperty->getValue($exception);
            foreach ($trace as &$call) {
                array_walk_recursive($call['args'], $flatten);
            }
            $traceProperty->setValue($exception, $trace);
        } while ($exception = $exception->getPrevious());
                $traceProperty->setAccessible(false);
    }
}

я также пытаюсь использовать класс JMS\HandlerCallback в классе JsonableException, но безуспешно в этом направлении.

person Igor Scabini    schedule 21.07.2017