在 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
,但没有成功。
我使用带有 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
,但没有成功。