如何使用Symfony 5.3 Serializer将对象关联数组序列化为指定JSON对象
方案1:通过字段序列化回调实现(无需自定义Normalizer,适合单字段定制)
直接在MyObject类的$b属性上绑定序列化逻辑即可,完全不影响a字段的原有序列化规则:
use Symfony\Component\Serializer\Annotation\Callback; class MyObject { // 其他属性省略 #[Callback(serialize: 'formatBField')] private iterable $b; // 字段序列化回调方法 public function formatBField(): array { $formatted = []; foreach ($this->b as $bItem) { $formatted[(string)$bItem->getId()] = $bItem; } return $formatted; } }
你原有的序列化代码无需做任何修改,Serializer会自动调用该回调处理b字段的输出格式。
方案2:自定义Normalizer(适合多场景复用规则)
如果多个字段都需要按照「对象ID为键、对象本身为值」的规则序列化,可以用自定义Normalizer实现复用:
- 先创建自定义Normalizer类
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; class IdKeyedCollectionNormalizer implements ContextAwareNormalizerInterface { public const ENABLE_ID_KEY = 'enable_id_key'; public function __construct( private ObjectNormalizer $innerNormalizer ) {} public function normalize($collection, string $format = null, array $context = []) { $result = []; foreach ($collection as $item) { $result[(string)$item->getId()] = $this->innerNormalizer->normalize($item, $format, $context); } return $result; } public function supportsNormalization($data, string $format = null, array $context = []): bool { return isset($context[self::ENABLE_ID_KEY]) && $context[self::ENABLE_ID_KEY] === true && is_iterable($data); } }
- 将自定义Normalizer注册到Serializer的normalizer列表中,注意要放在默认
ObjectNormalizer前面
$serializer = new Serializer([ new ArrayDenormalizer(), new DateTimeNormalizer(), // 新增自定义Normalizer new IdKeyedCollectionNormalizer(new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter, null, new ReflectionExtractor())), new ObjectNormalizer($classMetadataFactory, $metadataAwareNameConverter, null, new ReflectionExtractor(), null, null, []), ], [new JsonEncoder()]);
- 在需要启用该规则的字段上添加上下文注解
use Symfony\Component\Serializer\Annotation\Context; class MyObject { #[Context([IdKeyedCollectionNormalizer::ENABLE_ID_KEY => true])] private iterable $b; }
内容的提问来源于stack exchange,提问作者Constantine
相关产品推荐
相关产品推荐

