Symfony/ApiPlatform中children数组内parent属性序列化异常问题
解决Symfony/ApiPlatform自关联实体children中parent以IRI返回的问题
1. 统一序列化组配置
先检查实体中parent和children属性的序列化组是否一致,并确保嵌套关联也应用了相同的组。示例代码如下:
use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\ApiProperty; use Symfony\Component\Serializer\Annotation\Groups; use Doctrine\ORM\Mapping as ORM; #[ApiResource( normalizationContext: ['groups' => ['test:read']] )] #[ORM\Entity] class Test { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] #[Groups(['test:read'])] private ?int $id = null; #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ApiProperty(serializationContext: ['groups' => ['test:read']])] #[Groups(['test:read'])] private ?self $parent = null; #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[ApiProperty(serializationContext: ['groups' => ['test:read']])] #[Groups(['test:read'])] private Collection $children; // 构造函数、Getter/Setter等方法 }
关键是给parent和children都加上相同的序列化组,并通过ApiProperty明确指定嵌套关联的序列化上下文,确保children内部的parent也能被正确序列化。
2. 修正MaxDepth注解与循环引用配置
如果使用了MaxDepth,要确保注解同时应用在parent和children上,并且在normalizationContext中开启enable_max_depth:
use Symfony\Component\Serializer\Annotation\MaxDepth; #[ApiResource( normalizationContext: ['groups' => ['test:read'], 'enable_max_depth' => true] )] class Test { #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[Groups(['test:read'])] #[MaxDepth(2)] // 根据实际嵌套层级调整数值 private ?self $parent = null; #[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)] #[Groups(['test:read'])] #[MaxDepth(2)] private Collection $children; }
合理设置层级数值,既避免无限循环,又保证嵌套的parent能被序列化为对象。
3. 调整自定义归一化器逻辑(如果有)
如果之前写了自定义归一化器,确保它的优先级高于ApiPlatform默认归一化器,并且递归处理children中的parent:
use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; class TestNormalizer implements NormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; public function normalize($object, string $format = null, array $context = []): array { $data = [ 'id' => $object->getId(), 'parent' => $object->getParent() ? $this->normalizer->normalize($object->getParent(), $format, $context) : null, 'children' => array_map(fn($child) => $this->normalizer->normalize($child, $format, $context), $object->getChildren()->toArray()), // 其他字段 ]; return $data; } public function supportsNormalization($data, string $format = null, array $context = []): bool { return $data instanceof Test; } public function getPriority(): int { return 200; // 优先级高于默认归一化器(默认通常为100) } }
确保归一化children时,递归调用归一化器处理其parent,而非直接返回IRI。
4. 强制禁用IRI序列化
如果以上方法无效,可在parent属性上直接设置禁用IRI,强制序列化对象:
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ApiProperty(iris: false)] #[Groups(['test:read'])] private ?self $parent = null;
该配置会告诉ApiPlatform直接序列化关联对象,不再返回IRI字符串。
内容的提问来源于stack exchange,提问作者Евгений
相关产品推荐
相关产品推荐

