symfony7序列化对象为数组格式:
use Symfony\Component\Serializer\Serializer;
然后 Serializer 提供了如下方法normalize
$normalizedData = $this->normalize($data, $format, $context);
其中有个 $context 参数,这个参数很有用:
其作用主要包括以下几种情况:
1.控制属性的输出:可以通过设置 groups 来指定输出哪些属性。例如,['groups' => ['group_name']] 只会序列化属于 group_name 分组的属性。
2.属性的深度控制:可以通过 max_depth 设置序列化的最大深度。这个选项在对象嵌套层次很深时非常有用,避免无限递归。
3.回调自定义:你可以在 $context 中定义自定义回调函数,用于序列化前或反序列化后的数据处理。例如,可以为属性设置一个转换回调函数。
4.类型强制和格式控制:如果序列化到特定格式(例如 json 或 xml),可以在 $context 中设置格式的相关选项,使得规范化过程更灵活。
5.忽略空值:通过 skip_null_values 选项忽略空属性值,例如 ['skip_null_values' => true] 会跳过所有为 null 的属性。
可以看到定义的的DTO对象的属性有如下定义:
class TicketDto implements ResponsibleInterface
{
#[Groups("form")]
private ?int $id;
#[Groups(["table", "form"])]
private string $title;
#[Groups(["table"])]
private \DateTimeInterface $createdAt;
...
...
}
然后在控制器中,返回数据的时候:
return $this->apiResponse->response(new Dto\Query\TicketDto($ticket), context: ['groups' => 'form']); //这样只有在 form group中的属性才会被序列化, 我人为这样的好处是,对于同一个DTO,可以被复用,有些接口只需要其中一部分属性,这样就可以控制哪些可以返回给用户
再举个例子,关于回调的:
use Symfony\Component\Serializer\SerializerInterface;
$serializer = ...; // 假设已创建 Serializer 实例
$product = new ProductDTO("Sample Product", new \DateTime("2024-11-11"));
// 这个 context 会对其中的 createdAt 进行处理
$context = [
'groups' => ['table'], // 指定分组
'callbacks' => [
'createdAt' => function (\DateTimeInterface $date) {
return $date->format('Y-m-d'); // 自定义日期格式
}
]
];
$normalizedData = $serializer->normalize($product, 'json', $context);
print_r($normalizedData);
