如何在API Platform中用自定义归一化器处理JSON:API空关联
解决API Platform JSON:API格式下空关联返回空数组的问题
问题背景
在API Platform搭配JSON:API格式开发时,用基于Symfony\Component\Serializer\Normalizer\NormalizerInterface实现的自定义条目归一化器解析实体及其关联,遇到了空关联被JSON:API归一化器忽略的问题——即使设置skip_null_values为false也没用。
自定义归一化器代码:
class ApiItemNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { public function __construct(private readonly NormalizerInterface $decorated, ...) { ... } public function normalize($object, $format = null, array $context = []) { $responseObject = $this->decorated->normalize($object, $format, $context); ... } }
当前返回结果中,无关联的条目不会显示category字段:
"data": [ { "id": 2, "name": "does not have any relation", "created_at": "2023-04-24T11:46:16+02:00" }, { "id": 1, "name": "have two relations", "created_at": "2023-04-13T11:37:53+02:00", "category": [ { "name": "cat 1", "updated_by": null, "id": 1 }, { "name": "cat 2", "updated_by": null, "id": 3 } ] } ]
需求是让无关联的条目也返回category: []空数组。
可行解决方案
方案1:自定义归一化器中手动补全空字段
在normalize方法里,检查实体的关联属性,为空时手动添加空数组到返回结果:
public function normalize($object, $format = null, array $context = []) { $responseObject = $this->decorated->normalize($object, $format, $context); // 假设实体类是Item,关联属性为category if ($object instanceof Item) { if (!isset($responseObject['category']) || empty($responseObject['category'])) { $responseObject['category'] = []; } } return $responseObject; }
这种方式针对性强,适合只需要处理特定字段的场景。
方案2:实体类上配置并初始化关联集合
在实体的关联属性上通过注解配置强制输出,同时在构造函数中初始化集合为非空状态:
use ApiPlatform\Metadata\ApiProperty; use Symfony\Component\Serializer\Annotation\Groups; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; class Item { // ...其他属性 #[Groups(['item:read'])] #[ApiProperty(openapiContext: ['nullable' => false, 'default' => []])] private Collection $category; public function __construct() { // 初始化空集合,避免属性为null $this->category = new ArrayCollection(); } // ...对应的getter/setter方法 }
把关联属性初始化为ArrayCollection后,即使没有关联数据,属性本身也是空集合,JSON:API归一化器会自动序列化为空数组。
方案3:全局调整JSON:API归一化器配置
在config/packages/api_platform.yaml中配置全局序列化上下文,强制保留空值和空集合:
api_platform: formats: jsonapi: serializer: context: skip_null_values: false serialize_null: true
注意这个配置会影响所有字段,若只需特定字段生效,优先用前两种方案。
内容的提问来源于stack exchange,提问作者shayan
相关产品推荐
相关产品推荐

