在 Symfony 中使用 jms sirialize 包序列化错误

Serialize error with jms sirialize bundle in Symfony

我使用带有 jms 序列化包的 symfony 3。如何将具有堆栈跟踪的 exception/error 序列化为 JSON 以将其发送给客户端? An exception screenshot.

生成异常的助手:

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

我认为它发生是因为异常跟踪是一个非常庞大的结构:An example screenshot of exception trace

那么,如何序列化呢?如何使用 jms 序列化程序序列化巨大的结构?

我终于找到了这个要点: https://gist.github.com/Thinkscape/805ba8b91cdce6bcaf7c 并设法序列化异常。这不是关于有多大或有多复杂的问题,但有些字段是不可序列化的(如闭包或流)。

我将我的异常放在一个包含 class 中,并在其中 class 一个预序列化挂钩:

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);
        }
    }
}

while JsonableException extends Exception with function from 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);
    }
}

我也尝试在 JsonableException class 中使用 JMS\HandlerCallback,但没有成功。