Symfony Serializer 组件 CHANGELOG 全解析:从 2.1 到 8.2 的能力演进与关键配置指南

原创2026-10-03 17:32:551,964 阅读
文章标签:后端Web框架

Symfony Serializer 组件 CHANGELOG 全解析:从 2.1 到 8.2 的能力演进与关键配置指南

本指南以 src/Symfony/Component/Serializer/CHANGELOG.md 为骨架,梳理 Symfony Serializer 组件自 2.1 至 8.2 的能力演进史,并结合 Serializer 组件源码目录 中的 AbstractNormalizer、XmlEncoder、CsvEncoder、DateTimeNormalizer、UidNormalizer 等实现,深入讲解每个版本引入的核心上下文选项、属性、接口契约与破坏性变更。读完本文,你将能读懂该组件的版本演进脉络,掌握现代(7.x/8.x)Serializer 的配置方式,并能在升级旧代码时精准规避 BC Break。

一、文档定位:一份浓缩了十年设计决策的变更史

Serializer 组件负责把对象图(object graph)序列化为数组或其他格式(JSON、XML、CSV、YAML),并支持反向反序列化(组件 README)。CHANGELOG 是官方按版本逐条记录的变更清单,涵盖新增功能、弃用(deprecation)与破坏性变更(BC Break)。相比 README 的概览式说明,这份 CHANGELOG 蕴含了大量可追溯的工程决策——例如为什么 CsvEncoder 的 as_collection 默认值在 5.0 被改为 true、为什么 AdvancedNameConverterInterface 在 7.2 被并入 NameConverterInterface——这些细节对依赖该组件的老项目升级至关重要。

从源码结构看,Serializer 组件目录 由以下几个核心子域构成,与 CHANGELOG 的条目一一对应:

  • Normalizer/:负责对象与数组/标量之间的双向转换,Normalizer 实现清单 包含 ObjectNormalizer、PropertyNormalizer、GetSetMethodNormalizer、DateTimeNormalizer、UidNormalizer、BackedEnumNormalizer、NumberNormalizer、TranslatableNormalizer、ProblemNormalizer 等;
  • Encoder/:负责数组与具体格式(JSON/XML/CSV/YAML)之间的转换,如 XmlEncoder、CsvEncoder;
  • Mapping/:属性元数据、分组(Groups)、序列化名(SerializedName)、鉴别器映射(DiscriminatorMap)等元数据体系;
  • NameConverter/:属性名转换器,如 CamelCaseToSnakeCaseNameConverter、SnakeCaseToCamelCaseNameConverter、MetadataAwareNameConverter;
  • Attribute/ 与 Context/:PHP 原生属性(attribute)与上下文构建器(context builder);
  • 根目录的 Serializer.php 与 SerializerInterface.php:组件的门面与接口契约。

二、核心架构与上下文机制(2.x–4.x 奠定基础)

2.1 接口体系:Normalizer、Denormalizer、Encoder、Decoder

CHANGELOG 显示,2.1.0 是一个分水岭:Serializer 开始同时实现 NormalizerInterface、DenormalizerInterface、EncoderInterface、DecoderInterface 四类接口(见 Serializer.php 的实现)。2.2.0 起,所有接口都增加了可选的 $context 数组参数——这是整个组件可配置性的根基:$context 成为在调用时传递选项的唯一通道。

从 2.7.0 起引入的 AbstractNormalizer(AbstractNormalizer.php)将序列化/反序列化上下文常量集中定义,后续版本的所有上下文选项几乎都挂靠在它及其子类上。

2.2 默认上下文:现代配置方式的起点

4.2.0 明确提出“使用默认上下文(default context)是配置 normalizer 与 encoder 的推荐方式”,并弃用了直接向构造函数传一堆选项的做法。4.4.0/5.0.0 进一步移除了 AbstractNormalizer、AbstractObjectNormalizer、XmlEncoder 上的各类 setter(如 setCircularReferenceLimit()、setCallbacks()、setIgnoredAttributes()、setMaxDepthHandler()、XmlEncoder::setRootNodeName() 等),全部收敛为默认上下文。

这一点可以从源码得到印证:AbstractNormalizer 的构造函数签名即为 __construct(?ClassMetadataFactoryInterface $classMetadataFactory, ?NameConverterInterface $nameConverter, array $defaultContext = <a href="https://link.gitcode.com/i/18adc17af2e45df1fee9e163e20adcbb" target="_blank">]),并通过 array_merge 合并默认值([AbstractNormalizer.php);XmlEncoder 同样通过 __construct(array $defaultContext = <a href="https://link.gitcode.com/i/d585e830ff810bb72c65c0c1eb1b4ee3" target="_blank">]) 合并内置默认值([XmlEncoder.php)。这意味着现代写法是:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$encoders = [new XmlEncoder([
    XmlEncoder::ROOT_NODE_NAME => 'order',
    XmlEncoder::BOOLEAN_REPR => ['true', 'false'],
]), new JsonEncoder()];
$normalizers = [new ObjectNormalizer(null, null, null, null, null, [
    'skip_null_values' => true,
])];

$serializer = new Serializer($normalizers, $encoders);

2.3 常见历史上下文选项速查(2.x–4.x 引入)

版本 上下文选项 常量 作用
2.2 xml_root_name XmlEncoder::ROOT_NODE_NAME 配置 XML 根节点名
2.7 object_to_populate AbstractNormalizer::OBJECT_TO_POPULATE 反序列化时复用已有对象而非新建
3.4 DISABLE_TYPE_ENFORCEMENT AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT 类型不匹配时不抛 UnexpectedValueException
3.4 csv_headers CsvEncoder::HEADERS_KEY 传入 CSV 表头
4.2 skip_null_values AbstractObjectNormalizer::SKIP_NULL_VALUES 值为 null 的属性不输出
4.2 xml_type_cast_attributes XmlEncoder::TYPE_CAST_ATTRIBUTES 是否对 XML 属性做类型转换
4.2 XML 注释编码 — 编码 ['#comment' => ' foo '] 输出 <!-- foo -->
4.4 OUTPUT_UTF8_BOM_KEY CsvEncoder::OUTPUT_UTF8_BOM_KEY CSV 输出 UTF-8 BOM
4.4 API Problem 规范 ProblemNormalizer 按 RFC 7807 规范化错误输出
5.0 构造函数默认值 DEFAULT_CONSTRUCTOR_ARGUMENTS 对象构造参数缺失时提供默认值
5.3 END_OF_LINE CsvEncoder::END_OF_LINE 自定义 CSV 行结束符
5.4 PRESERVE_EMPTY_OBJECTS — 空集合保留为 ArrayObject

三、8.x 时代的新能力(以最新版为纲)

CHANGELOG 把 8.2 列在最前,这也是当前仓库的主版本。这一节先讲 8.x 引入的新特性,再逐层回溯。

3.1 8.2:独立 SerializerBundle 与精细化上下文

8.2 的变更核心是把 Serializer 集成从 FrameworkBundle 抽离:

  • 新增 SerializerBundle:提供 serializer 配置,以及此前由 FrameworkBundle 在 framework.serializer 下提供的全部服务;
  • 新增 CacheWarmer\SerializerCacheWarmer:由 FrameworkBundle 迁移而来的缓存预热器,用于预热序列化元数据缓存;
  • 新增 Mapping\Loader\LoaderChain 的可选参数 $mappedClasses:声明每个 loader 映射哪些类;
  • 新增 LoaderChainAwareInterface:让 LoaderChain 中的 loader 可以等所有 loader 运行完毕后再执行收尾工作,随后 LoaderChain 会统一校验以任意格式声明的鉴别器映射。

这两项与 CacheWarmer 目录 和 Mapping/Loader 相关源码 相互印证,说明 8.2 起 Serializer 已具备完整的独立 Bundle 生命周期。

3.1.1 反序列化的两个容错选项

AbstractNormalizer 在 8.2 新增了两个上下文常量(AbstractNormalizer.php):

  • SKIP_INVALID_ATTRIBUTES('skip_invalid_attributes'):反序列化时,值无法使用的属性按“输入中不存在”处理——构造参数回退到 DEFAULT_CONSTRUCTOR_ARGUMENTS,再回退到参数默认值,最后回退到 null(若可空);普通属性则保持不动,且不报告任何错误。源码注释明确指出它与 ALLOW_EXTRA_ATTRIBUTES 的分工:后者覆盖“类不认识的属性”,前者覆盖“类认识但无法使用的属性”(AbstractNormalizer.php);
  • IGNORED_GROUPS('ignored_groups'):无论当前允许哪些分组,直接排除属于指定分组的属性,与 GROUPS 形成“白名单 + 黑名单”的组合控制(AbstractNormalizer.php);
  • ENABLE_DEFAULT_GROUPS('enable_default_groups'):未显式标注 #<a href="https://link.gitcode.com/i/098cb7e291d5acb356b7ae538ee7cc54" target="_blank">Groups] 的属性,默认纳入隐式的 Default 分组与类短名分组,与 Validator 组件 Default 分组的约定对齐([AbstractNormalizer.php)。

3.1.2 类型系统与鉴别器增强

  • 支持反序列化联合类型数组,如 array<Foo|Bar>;
  • 支持按组配置序列化名与路径:#[SerializedName]、#[SerializedPath] 可重复使用,YAML 提供 serialized 键、XML 提供 <serialized> 元素;
  • 泛型模板类型在反序列化时被解析:例如 Box<Circle> 类型属性中的模板参数 T 会被反序列化为 Circle;
  • 新增 DiscriminatorMapType,允许从被映射的子类扩展鉴别器映射;DiscriminatorMap 的 mapping 参数变为可选,并在元数据加载阶段与 defaultType 一起校验;
  • 对象属性用于鉴别类型时:多个类型映射到同一类时使用其鉴别器属性选型;属性未设置或未知时使用第一个声明的类型;
  • 反序列化“非列表数组到 list 类型属性”时触发弃用警告;
  • 启用 PropertyInfo 组件的 #[WithAccessors] 与 Serializer 协同工作。

3.1.3 XmlEncoder 与 CsvEncoder 的 8.2 新选项

  • XmlEncoder::FORCE_COLLECTION('force_collection'):指定某些标签即使只有一个子节点也始终解码为集合。源码默认值为 <a href="https://link.gitcode.com/i/2496a115f4cfddbde74be57ea8840fd3" target="_blank">],其含义在常量注释中写明“即使只有一个子节点也始终视为集合的 XML 标签数组”([XmlEncoder.php);
  • XmlEncoder::BOOLEAN_REPR('xml_boolean_repr'):指定编码时布尔值的字符串表示,例如 <a href="https://link.gitcode.com/i/9fcd2c0c16c6e96f23b241d63f6c407e" target="_blank">'true', 'false'] 或 ['yes', 'no'];默认不设置时布尔值按 1/0 输出([XmlEncoder.php);
  • CsvEncoder::HEADERS_KEY 支持关联数组:编码时用 <a href="https://link.gitcode.com/i/58085a338e635679421580a1d5b28f95" target="_blank">'Name' => 'name', 'Email' => 'user.email'] 这样的映射把列标签映射到扁平化行的路径,只输出所列列且按给定顺序排列([CsvEncoder.php)。常规列表形式的 HEADERS_KEY 则用于指定列名顺序,多余列追加在其后。

3.2 8.1:反序列化错误收集与类型转换

  • AbstractObjectNormalizer::ENABLE_TYPE_CONVERSION:标量类型转换。源码注释说明,未显式设置时,对 XML 与 CSV 格式默认启用(因为这两种格式的基本类型都是字符串),默认值在进入子上下文时按最外层 $format 计算一次并传播(AbstractObjectNormalizer.php);
  • Serializer::COLLECT_EXTRA_ATTRIBUTES_ERRORS:反序列化时收集额外属性错误而非立即抛出;
  • PartialDenormalizationException::getErrors() 被弃用,改用 getNotNormalizableValueErrors();
  • BackedEnumNormalizer 的 NotNormalizableValueException 消息包含更多有用信息。

3.3 8.0:接口收敛与清理(BC Break)

  • 删除 CsvEncoder::ESCAPE_CHAR_KEY 常量及转义字符功能,并删除 CsvEncoderContextBuilder::withEscapeChar();

  • 删除 AbstractNormalizerContextBuilder::withDefaultContructorArguments()(拼写错误的重载),改用 withDefaultConstructorArguments();

  • NameConverterInterface 方法签名扩展:normalize() 与 denormalize() 从单一参数改为四个参数。CHANGELOG 给出了前后对照:

    // Before
    public function normalize(string $propertyName): string;
    public function denormalize(string $propertyName): string;
    
    // After
    public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string;
    public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string;
    
  • 删除 AdvancedNameConverterInterface,统一使用 NameConverterInterface;

  • 删除编译期元数据体系:ClassMetadataFactoryCompiler、CompiledClassMetadataFactory、CompiledClassMetadataCacheWarmer 全部移除(这些类在 5.2.0 引入、7.3 起被弃用,最终在 8.0 完成清理);

  • 删除 Annotation 命名空间的类别名,全面转向原生 attribute;attribute 类中的 getter 方法被移除,改为直接使用公有属性。

四、7.x:从 attribute 化到多实例支持

4.1 7.0/7.1:接口的“无上下文”清理与默认分组

7.0 是一轮重要的 BC Break 与接口现代化:

  • DenormalizerInterface 与 NormalizerInterface 新增 getSupportedTypes() 方法,取代 CacheableSupportsMethodInterface(后者在 6.3 被弃用);
  • 删除 ContextAwareNormalizerInterface 与 ContextAwareDenormalizerInterface(6.1 弃用),统一并入 NormalizerInterface/DenormalizerInterface;
  • supportsNormalization()/supportsDenormalization() 增加 $context 参数;
  • 移除 Doctrine annotations 支持(6.4 起弃用),AnnotationLoader 由 AttributeLoader 取代(6.4 弃用、7.0 移除);
  • UidNormalizer 不再支持反序列化为抽象类 AbstractUid,必须使用其子类之一;对抽象类反序列化会抛出 \Error;
  • AttributeMetadata::setSerializedName() 与 ClassMetadata::setClassDiscriminatorMapping() 的参数变为必填(6.2 起弃用无参调用)。

7.1 延续了上下文选项的精细化:

  • DateTimeNormalizer::CAST_KEY('datetime_cast'):反序列化日期时指定强转目标类型(源码默认值为 null,见 DateTimeNormalizer.php);
  • AbstractNormalizer::FILTER_BOOL:用 filter_var(..., FILTER_VALIDATE_BOOL) 预处理后再强转布尔值,"0"、"false"、"off"、"no"、"" 转 false,"1"、"true"、"on"、"yes" 转 true(AbstractNormalizer.php);
  • “Default 与类名默认分组”上线(8.2 的 ENABLE_DEFAULT_GROUPS 正是把它变成显式开关);
  • CamelCaseToSnakeCaseNameConverter::REQUIRE_SNAKE_CASE_PROPERTIES:要求属性本身为 snake_case;
  • XmlEncoder::CDATA_WRAPPING_PATTERN:自定义触发 CDATA 包装的正则模式。

4.2 7.2:多实例与名称转换器

  • 多 Serializer 实例配置:可配置多个 serializer 实例,各自拥有不同的默认上下文、名称转换器、normalizer 与 encoder 集合,并可配置多个实例的集合(collection profiles)——这为同一应用内多套序列化契约提供了官方支持;
  • 新增 SnakeCaseToCamelCaseNameConverter:与已有的 CamelCaseToSnakeCaseNameConverter 互补;
  • UidNormalizer::NORMALIZATION_FORMAT_RFC9562:RFC 9562 取代 RFC 4122 后新增的格式常量。源码显示它等价于 NORMALIZATION_FORMAT_RFC4122,因为“RFC 9562 废弃了 RFC 4122 但格式相同”(UidNormalizer.php)。UidNormalizer 支持 canonical、base58、base32、rfc4122 四种规范化格式(UidNormalizer.php),默认 canonical;
  • DateTimeNormalizer 支持 \DateTime/\DateTimeImmutable 子类的反序列化;
  • 弃用 CsvEncoder::ESCAPE_CHAR_KEY 与 CsvEncoderContextBuilder::withEscapeChar()(8.0 移除)。

4.3 7.3/7.4:鉴别器与编译元数据终结

  • 7.3:DiscriminatorMap 新增 defaultType;新增 NumberNormalizer 把 BcMath\Number 与 GMP 规范化为字符串;为命名 serializer 注册 NormalizerInterface/DenormalizerInterface 别名;弃用 CompiledClassMetadataFactory 与 CompiledClassMetadataCacheWarmer;
  • 7.4:新增 #[ExtendsSerializationFor] 与 AttributeMetadataPass(用 attribute 在编译期声明约束元数据);XmlEncoder 新增 CDATA_WRAPPING_NAME_PATTERN 与 PRESERVE_NUMERIC_KEYS;AttributeLoader 支持 can*() 方法;AttributeMetadata 与 ClassMetadata 变为 final;弃用 ClassMetadataFactoryCompiler;DateTimeNormalizer 新增 FORCE_TIMEZONE_KEY 在反序列化时强制时区。

五、6.x:Web Profiler 集成与注解过渡

  • 6.1:新增 TraceableSerializer、TraceableNormalizer、TraceableEncoder 与 SerializerDataCollector,接入 Web Profiler 面板;新增上下文构建器(context builder)机制,如 ObjectNormalizerContextBuilder、CsvEncoderContextBuilder 等,用流式 API 替代手写数组;ObjectNormalizer 支持 can*() 方法。
  • 6.2:Context attribute 支持构造器属性提升(constructor promoted properties);PropertyNormalizer::NORMALIZE_VISIBILITY 用位掩码(NORMALIZE_PUBLIC/NORMALIZE_PROTECTED/NORMALIZE_PRIVATE)控制可见性;新增 SerializedPath attribute 把嵌套属性扁平化;YamlEncoder::YAML_INDENTATION 允许在服务配置中控制 YAML 缩进。
  • 6.3:AbstractNormalizer::REQUIRE_ALL_PROPERTIES 要求输入中必须列出全部属性,不再对可空属性回退为 null(AbstractNormalizer.php);XmlEncoder::SAVE_OPTIONS(保存 XML 时的 LIBXML_* 位字段,默认 0);BackedEnumNormalizer::ALLOW_INVALID_VALUES;新增 UnsupportedFormatException;ProblemNormalizer 可输出 ValidationFailedException 与 PartialDenormalizationException 的细节。
  • 6.4:新增 TranslatableNormalizer;Context attribute 可作用于类;Groups attribute/注解可作用于类;JsonDecode 新增 json_decode_detailed_errors 选项;XmlEncoder::CDATA_WRAPPING;为 Annotation 命名空间下所有类提供 Attribute 别名(过渡期的双轨支持,7.0/8.0 逐步移除注解)。

六、5.x:枚举、Uid 与编译元数据实验

  • 5.0(BC Break 密集版):创建 Serializer 时若 normalizer 不实现 NormalizerInterface 或 DenormalizerInterface(encoder 不实现 EncoderInterface/DecoderInterface)将直接抛异常;CsvEncoder 的 as_collection 默认值改为 true(4.4 起弃用旧默认值);移除 AbstractNormalizer 与 AbstractObjectNormalizer 上的全部公开配置属性与 setter,统一走默认上下文。
  • 5.1:支持标量值反序列化;ObjectNormalizer 支持 \stdClass;新增 #[Ignore] 属性忽略指定属性;可序列化约束违例的 payload(如 severity)。
  • 5.2:引入 CompiledClassMetadataFactory 与 ClassMetadataFactoryCompiler(编译期元数据,7.3 弃用、8.0 移除);新增 UidNormalizer、FormErrorNormalizer、MimeMessageNormalizer;serializer mapping 支持 PHP attribute 配置。
  • 5.3:可用元数据提供 (de)normalization 上下文(#[Context] attribute);UidNormalizer 引入规范化格式。
  • 5.4:支持 PHP backed enumeration(BackedEnumNormalizer);空数组可序列化为对象;PRESERVE_EMPTY_OBJECTS 时空集合以 ArrayObject 返回;反序列化时收集类型错误。

七、XML 与 CSV 编码器的完整上下文选项速查

7.1 XmlEncoder

CHANGELOG 中 XmlEncoder 相关的条目最多,这里结合源码(XmlEncoder.php)给出完整选项表:

上下文键(常量) 默认值 说明
FORMAT 'xml' 格式标识
AS_COLLECTION false 是否把所有标签视为集合
FORCE_COLLECTION [] 强制按集合解码的标签数组(8.2 新增)
DECODER_IGNORED_NODE_TYPES [XML_PI_NODE, XML_COMMENT_NODE] 解码时忽略的 DOM 节点类型
ENCODER_IGNORED_NODE_TYPES [] 编码时忽略的 DOM 节点类型
ENCODING — XML 编码声明
FORMAT_OUTPUT — 是否格式化输出
LOAD_OPTIONS LIBXML_NONET | LIBXML_NOBLANKS 加载文档的 LIBXML_* 位字段
SAVE_OPTIONS 0 保存文档的 LIBXML_* 位字段(6.3 新增)
REMOVE_EMPTY_TAGS false 是否移除空标签
ROOT_NODE_NAME 'response' 根节点名
STANDALONE — XML standalone 声明
TYPE_CAST_ATTRIBUTES true 是否对 XML 属性做类型转换(旧名 TYPE_CASE_ATTRIBUTES,4.4 弃用)
VERSION — XML 版本声明
CDATA_WRAPPING true 是否启用 CDATA 包装(6.4 新增)
CDATA_WRAPPING_NAME_PATTERN false 按标签名匹配的 CDATA 包装模式(7.4 新增)
CDATA_WRAPPING_PATTERN '/[<>&]/' 内容匹配该正则时用 CDATA 包装(7.1 新增)
IGNORE_EMPTY_ATTRIBUTES false 是否忽略空属性
PRESERVE_NUMERIC_KEYS false 解码时是否保留数字键(7.4 新增)
BOOLEAN_REPR null 布尔值的字符串表示,如 ['true','false'];默认输出 1/0(8.2 新增)

值得一提的历史点:2.1.0 曾把 item 标签从“整个标签变为数组”视为 BC Break,CHANGELOG 给出了转换前后对照(从空数组变为 Array([item] => Array([0]=>…)) 结构),这正是后来 AS_COLLECTION/FORCE_COLLECTION 选项要解决的问题。

7.2 CsvEncoder

结合 CsvEncoder.php:

上下文键(常量) 默认值 说明
FORMAT 'csv' 格式标识
DELIMITER_KEY ',' 分隔符
ENCLOSURE_KEY '"' 包围符
KEY_SEPARATOR_KEY '.' 嵌套键分隔符(扁平化用)
HEADERS_KEY [] 表头;列表形式定顺序,关联数组形式做列映射与重排(8.2 增强)
ESCAPE_FORMULAS_KEY false 是否转义公式注入字符(= - + @ 等,源码常量 FORMULAS_START_CHARACTERS)
AS_COLLECTION_KEY true 解码时是否返回集合(5.0 起默认 true)
NO_HEADERS_KEY false 是否输出表头行
END_OF_LINE "\n" 行结束符(5.3 新增)
OUTPUT_UTF8_BOM_KEY false 是否输出 UTF-8 BOM(4.4 新增)

注意:ESCAPE_CHAR_KEY 与 withEscapeChar() 已在 7.2 弃用、8.0 删除,迁移时请删除相关配置。

八、升级路线与兼容性速查

综合 CHANGELOG 的弃用与移除记录,可以归纳出几条明确的升级红线:

  1. 注解(annotations)已死,attribute 为王:6.4 为 Annotation 命名空间提供别名过渡,7.0 移除 AnnotationLoader 与 Doctrine annotations 支持,8.0 移除类别名与 attribute 类 getter。新代码一律使用 #[Groups]、#[SerializedName]、#[SerializedPath]、#[Ignore]、#[Context]、#[DiscriminatorMap] 等原生 attribute。
  2. 名称转换器接口统一:7.1 给 NameConverterInterface 增加 $class/$format/$context 参数,8.0 移除 AdvancedNameConverterInterface,任何自定义名称转换器都需要升级到四参数签名。
  3. 上下文配置取代构造参数与 setter:从 4.2 的默认上下文推荐开始,5.0 移除全部公开配置属性/setter,现代代码用 $defaultContext 数组或 context builder 配置。
  4. 接口瘦身:ContextAwareNormalizerInterface/ContextAwareDenormalizerInterface/CacheableSupportsMethodInterface 已分别于 7.0/7.0/6.3 起不再需要,统一以 NormalizerInterface/DenormalizerInterface 及 getSupportedTypes() 为准。
  5. CSV 行为默认值:as_collection 默认 true(5.0);ESCAPE_CHAR_KEY 已删除(8.0)。
  6. Uid 反序列化目标类:必须使用 AbstractUid 的具体子类(Uuid/Ulid 等),禁止反序列化为抽象基类(7.0)。

九、验证途径:测试用例与迁移工具

仓库为 Serializer 提供了完整的测试覆盖,位于 Tests 目录,例如 Normalizer、Encoder、Mapping 等子目录下的用例,可用于验证本节描述的上下文选项与 BC Break 行为。升级老项目时,可结合 CHANGELOG 中“弃用 → 移除”的时间线逐版本核对,并关注以下两类信号:

  • 运行测试时出现的 deprecation 警告(如 8.1 的反序列化 list 类型警告、7.1 的日期默认格式解析警告);
  • 编译期元数据相关的类引用(CompiledClassMetadataFactory 等已在 8.0 删除)。

结语

从 2.1 的接口雏形,到 4.2 的默认上下文革命,再到 7.x 的 attribute 化与多实例支持、8.x 的独立 Bundle 与类型系统深化,Symfony Serializer 的演进始终围绕同一个目标:让“对象 ↔ 数组 ↔ 格式”的转换既灵活又可预测。这份 CHANGELOG 不只是变更清单,更是一份浓缩的架构决策记录——掌握它,你就掌握了该组件从“能用”到“好用”的全部关键路径。

登录后查看全文
symfony