您的位置:

处理symfony出现报错LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class))

  发布时间:2024-12-09 20:26:44
Symfony Serializer组件不支持JsonSerializable接口的对象进行反序列化操作,解决方法是自定义数据正常化器。示例代码展示了创建和使用自定义Normalizer的步骤。

问题原因

Symfony出现LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class))的原因是因为Symfony Serializer组件在尝试使用JsonSerializable接口进行反序列化时会抛出该异常。由于JsonSerializable接口仅用于对象的序列化,而Serializer组件默认工作在反序列化模式下,因此尝试使用JsonSerializable接口进行反序列化是不合适的,会导致该异常的发生。

解决方案

出现LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class))的原因是Symfony Serializer组件不支持JsonSerializable接口的对象进行反序列化操作。解决这个问题的方法是自定义一个数据正常化器(Data Normalizer),在这个正常化器中实现对JsonSerializable对象的处理逻辑。下面是一个解决该问题的示例代码:


use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class JsonSerializableNormalizer implements ContextAwareNormalizerInterface
{
    public function supportsNormalization($data, string $format = null, array $context = [])
    {
        return $data instanceof \JsonSerializable;
    }

    public function normalize($object, string $format = null, array $context = [])
    {
        return $object->jsonSerialize();
    }
}

// 在Serializer中注册自定义的正常化器
$serializer = new Symfony\Component\Serializer\Serializer([new JsonSerializableNormalizer()], [new JsonEncoder()]);

// 使用Serializer进行数据的反序列化
$denormalizedObject = $serializer->deserialize($jsonString, YourObjectClass::class, 'json');

通过自定义数据正常化器来处理JsonSerializable接口的对象,可以绕过Symfony Serializer组件默认的处理方式,成功地反序列化JsonSerializable对象。

具体例子

出现LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class))的原因是在使用Symfony序列化/反序列化组件时,试图对实现了\JsonSerializable接口的对象进行反序列化操作。然而,Symfony默认的Serializer组件并不支持使用\JsonSerializable对象进行反序列化,因此会触发该异常。 要解决这个问题,我们可以创建一个自定义的Normalizer来处理\JsonSerializable对象的反序列化。我们可以扩展Symfony的AbstractNormalizer类,并在supportsNormalization和supportsDenormalization方法中添加对\JsonSerializable对象的支持。 下面是一个示例代码,展示如何正确使用自定义Normalizer来处理\JsonSerializable对象的反序列化:


use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class JsonSerializableNormalizer extends AbstractNormalizer
{
    public function supportsDenormalization($data, $type, $format = null)
    {
        return is_a($type, \JsonSerializable::class, true);
    }

    public function denormalize($data, $class, $format = null, array $context = [])
    {
        // 自定义JsonSerializable对象的反序列化逻辑
        // 这里可以根据JsonSerializable对象的数据结构进行反序列化操作
        // 返回一个反序列化后的JsonSerializable对象
    }
}

// 使用自定义的Normalizer
$serializer = new \Symfony\Component\Serializer\Serializer([new JsonSerializableNormalizer()], []);

// 示例JsonSerializable对象
$jsonData = '{"key": "value"}';

// 反序列化Json数据至JsonSerializable对象
$jsonSerializableObj = $serializer->deserialize($jsonData, CustomJsonSerializableClass::class, 'json');

var_dump($jsonSerializableObj);

通过上述代码示例,我们创建了一个名为JsonSerializableNormalizer的自定义Normalizer,该Normalizer可以处理对实现\JsonSerializable接口的对象的反序列化操作。然后,我们实例化了Symfony的Serializer,并传入了自定义Normalizer来进行反序列化操作。最后,我们使用deserialize方法将JSON数据反序列化为JsonSerializable对象。