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

时间:2017-06-01 16:52:11

标签: php symfony jmsserializerbundle

我使用symfony 3和jms serialize bundle。如何序列化具有堆栈跟踪到JSON的异常/错误以将其发送到客户端? An exception screenshot. enter image description here

生成例外的助手:

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 enter image description here

那么,如何序列化呢?如何使用jms序列化器序列化大型结构?

1 个答案:

答案 0 :(得分: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使用来自gist:

的函数扩展Exception
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,但在这方面没有成功。