You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony反序列化ApiPlatform MongoDB Paginator构造参数缺失问题问询

问题根因

ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator 是依赖数据库游标(mongoDbOdmIterator)的运行时对象,该游标属于和数据库连接绑定的资源类型,本身不支持序列化存储。直接序列化整个Paginator对象只会序列化公共属性,反序列化时无法恢复依赖的游标实例,因此抛出构造参数缺失的错误:

无法基于序列化数据创建"\ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator"实例,因为其构造函数要求传入参数"mongoDbOdmIterator"。

推荐实现方案

不直接序列化Paginator对象,提前提取业务需要的结果集数据和分页元数据后再序列化,反序列化后可按需构造兼容接口的分页对象,性能和可维护性更高,实现代码如下:

序列化阶段

$paginator = $this->getCollectionResults($aggregationBuilder, $resourceClass, $operationName, $context);
// 提取可序列化的分页数据
$cacheData = [
    'items' => iterator_to_array($paginator->getIterator()), // 实际查询结果集
    'totalItems' => $paginator->getTotalItems(), // 总数据条数
    'currentPage' => $paginator->getCurrentPage(), // 当前页码
    'itemsPerPage' => $paginator->getItemsPerPage(), // 每页条数
    // 可追加其他需要的分页元数据
];
// 序列化后存入Redis
$serialized = $this->serializer->serialize($cacheData, 'json');

反序列化阶段

如果需要返回和原Paginator接口兼容的对象,可使用ArrayIterator构造虚拟Paginator实例,不需要依赖真实数据库游标:

$cacheData = $this->serializer->deserialize($serialized, 'array', 'json');
// 构造虚拟Paginator实例,适配原有逻辑的类型约束
$paginator = new \ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator(
    new \ArrayIterator($cacheData['items']),
    $cacheData['totalItems'],
    $cacheData['itemsPerPage'],
    $cacheData['currentPage']
);

备选方案:自定义序列化处理器

如果需要让序列化逻辑透明处理Paginator类型,无需修改原有业务代码,可以给Symfony序列化器注册针对该类的自定义Normalizer:

  1. 创建自定义Normalizer类
use ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Paginator;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class MongoPaginatorNormalizer implements NormalizerInterface, DenormalizerInterface
{
    public function normalize($object, string $format = null, array $context = []): array
    {
        /** @var Paginator $object */
        return [
            'items' => iterator_to_array($object->getIterator()),
            'totalItems' => $object->getTotalItems(),
            'currentPage' => $object->getCurrentPage(),
            'itemsPerPage' => $object->getItemsPerPage(),
        ];
    }

    public function supportsNormalization($data, string $format = null): bool
    {
        return $data instanceof Paginator;
    }

    public function denormalize($data, string $type, string $format = null, array $context = [])
    {
        return new Paginator(
            new \ArrayIterator($data['items']),
            $data['totalItems'],
            $data['itemsPerPage'],
            $data['currentPage']
        );
    }

    public function supportsDenormalization($data, string $type, string $format = null): bool
    {
        return $type === Paginator::class;
    }
}
  1. 注册到序列化器即可直接对Paginator对象序列化/反序列化
$normalizers = [new MongoPaginatorNormalizer(), new ObjectNormalizer()];
$serializer = new Serializer($normalizers, [new JsonEncoder()]);

// 直接序列化Paginator对象
$serialized = $serializer->serialize($paginator, 'json');
// 直接反序列化还原Paginator对象
$paginator = $serializer->deserialize($serialized, Paginator::class, 'json');

内容的提问来源于stack exchange,提问作者Matthew Zarbatany

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:27:03