Symfony Serializer递归跳过空值:多层对象空值未移除求解
如何用Symfony Serializer递归跳过所有层级的空值
嘿,我之前也踩过这个坑!Symfony Serializer默认的skip_null_values选项确实只对顶层对象生效,嵌套对象里的null值不会被自动过滤。要实现递归跳过所有层级的空值,有两种简洁的解决方案,我给你详细说说:
方法1:配置ObjectNormalizer的默认上下文(推荐)
最直接的方式是给ObjectNormalizer设置默认的序列化上下文,确保skip_null_values参数在处理嵌套对象时也能被继承。这样不需要写额外的自定义代码,利用Symfony内置的功能就能搞定。
在Symfony项目中通过配置文件实现
如果是Symfony框架项目,直接修改config/services.yaml:
services: Symfony\Component\Serializer\Normalizer\ObjectNormalizer: arguments: $defaultContext: skip_null_values: true Symfony\Component\Serializer\Serializer: arguments: - ['@Symfony\Component\Serializer\Normalizer\ObjectNormalizer'] - ['@Symfony\Component\Serializer\Encoder\JsonEncoder']
手动创建Serializer的代码实现
如果是在非框架环境下手动构建Serializer:
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Encoder\JsonEncoder; // 创建ObjectNormalizer时,把skip_null_values设为默认上下文 $normalizer = new ObjectNormalizer(null, null, null, null, null, null, [ 'skip_null_values' => true, ]); $encoder = new JsonEncoder(); $serializer = new Serializer([$normalizer], [$encoder]); // 测试你的对象 $testObject = (object) [ 'key1' => null, 'key2' => null, 'key3' => (object) ['keyA' => null, 'keyB' => 'value'], 'key4' => 'value', ]; $jsonResult = $serializer->serialize($testObject, 'json'); // 输出结果:{"key3":{"keyB":"value"},"key4":"value"}
方法2:自定义Normalizer(兼容旧版本Symfony)
如果你的Symfony版本比较旧,或者默认上下文的方式不生效,可以自定义一个Normalizer,继承ObjectNormalizer并增强递归过滤逻辑:
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; class RecursiveSkipNullNormalizer extends ObjectNormalizer { public function normalize($object, string $format = null, array $context = []) { // 强制开启空值跳过 $context['skip_null_values'] = true; // 调用父类方法获取初始序列化数据 $data = parent::normalize($object, $format, $context); // 递归过滤嵌套的数组/对象中的空值 if (is_array($data) || $data instanceof \ArrayObject) { return array_filter($data, function ($value) use ($format, $context) { if (is_object($value) || is_array($value)) { // 对嵌套结构递归处理,空对象/空数组也会被过滤 $normalized = $this->normalize($value, $format, $context); return !empty($normalized); } return null !== $value; }); } return $data; } }
然后使用这个自定义Normalizer构建Serializer:
$customNormalizer = new RecursiveSkipNullNormalizer(); $encoder = new JsonEncoder(); $serializer = new Serializer([$customNormalizer], [$encoder]); // 序列化后会递归移除所有层级的null值和空的嵌套结构
为什么默认的skip_null_values不递归?
简单来说,Symfony的skip_null_values默认只作用于当前层级的对象属性,当序列化嵌套对象时,默认不会自动将这个上下文参数传递给子对象的序列化过程。通过设置默认上下文或自定义Normalizer,我们可以强制让这个规则在所有层级生效。
内容的提问来源于stack exchange,提问作者Dylan Bourdere
相关产品推荐
相关产品推荐

