我使用symfony 3和jms serialize bundle。如何序列化具有堆栈跟踪到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序列化器序列化大型结构?
答案 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
,但在这方面没有成功。