php - symfony/serializer 中的泛型
问题描述
我使用 symfony 序列化程序来反序列化 REST 服务器对对象的回答。
服务器返回的数据是这样的(伪代码,答案本身是 JSON):
// Endpoint 1
class Paginated {
public items:Object1[]
public page:int
}
// Endpoint 2
class Paginated {
public: items:Object2[]
public page:int
}
因此,每个答案都包含在同一个“分页”对象中。
我不想重复每个对象中的公共成员,我想在我的 Symfony 应用程序中以与此伪代码中描述的相同方式实现对象。
问题是,PHP 不支持泛型来键入提示“items”成员,并且 symfony 序列化程序似乎没有提供类似的东西。
那么,解决这个问题的最佳方法是什么?
解决方案
解决此问题的一种简单方法是使用回调上下文选项。在该回调中,您可以自己反序列化要传递给 Paginated 的对象。然后,对于要在分页中支持的每种对象类型,您将拥有不同的回调并注册它。它不必像文档中显示的那样是一个闭包,您也可以使用一个类__invoke()
来使其更容易在不同的地方重用。
另一种更一般地解决这个问题的方法是,通过编写一个自定义的非规范化器来实现DenormalizerAwareInterface
(因此它可以将嵌套项的非规范化委托回序列化器。
就像 Symfony 可以识别Object[]
对象列表一样,您可以创建自己的自定义类型约定来模拟 Generic。
假设您希望它类似于Paginated<Object1>
,那么您的序列化程序调用可能看起来像这样:
$serializer->deserialize($json, Paginated::class . '<' . Object1::class . '>', 'json');
然后,您的(反)规范化器将支持与正则表达式匹配的类型。在 denormalize 方法中,您将获取 json 的数组结构,调用类似 `$denormalizedItems = $this->denormalizer->denormalize($data['items'], Object1::class . '[]'); 然后将它们放入您的分页对象中。大致是这样的:
public function denormalize($data, string $type, string $format = null, array $context = [])
{
$extractedObjectType = ...; #extract class name inside <>
$data['items'] = $this->denormalizer->denormalize($data['items'], $extractedType, $format, $context);
// Option 1: Delegate denormalizing Paginated with the adjusted data
return $this->denormalizer->denormalize($data, Paginated::class, $format, $context);
// Option 2: Denormalize Paginated yourself and pass adjusted data as argument
return new Paginated($data['items'], (int) $data['page']);
}
推荐阅读
- javascript - 如何使用 JS/JQuery 从表单中获取数据并使用 yii2 将信息传递给控制器?
- php - 使用 ccxt 加密 API 的 ETH/BTC 套利交易在创建买单时抛出错误
- python-3.x - Spyder 不会为 matplotlib 绘图释放内存
- oracle - 无法使用 OCI Storage Gateway 挂载我的 Storage Gateway 文件系统
- c++ - 我在这个 while 循环中错过了什么?
- neural-network - 如何将更多图像输入到 caffe 模型中?
- vim - 是否有任何与ideavim 兼容的vim 片段插件?
- delphi - 如何在 Delphi 7 中访问已连接 USB 设备的硬件属性?
- amazon-web-services - AWS - 如何为 AWS 服务分离每个用户的资源
- javascript - 比较具有不同格式的Javascript中的两个日期