如何创建JMSSerialization指定基础类型属性的自定义(反)序列化处理器
解决方案
核心实现思路是注册自定义类型别名的专属处理器,只有标注了对应自定义类型的属性才会触发处理器逻辑,完全不影响全局基础类型的默认规则,也不需要修改类源码新增额外的get/set方法。
步骤1:实现自定义类型处理器
以你需要的CSV数组转换为例,处理器示例如下:
use JMS\Serializer\Handler\SubscribingHandlerInterface; use JMS\Serializer\GraphNavigator; use JMS\Serializer\JsonSerializationVisitor; use JMS\Serializer\JsonDeserializationVisitor; use JMS\Serializer\Context; class CsvArrayHandler implements SubscribingHandlerInterface { public static function getSubscribingMethods() { return [ [ 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'format' => 'json', 'type' => 'csv_array', // 自定义专属类型名,不要用默认的array 'method' => 'serializeCsvArray', ], [ 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 'format' => 'json', 'type' => 'csv_array', 'method' => 'deserializeCsvArray', ], ]; } // 序列化:数组转CSV字符串 public function serializeCsvArray(JsonSerializationVisitor $visitor, array $data, array $type, Context $context) { // 可根据需求自定义CSV转义、分隔符等逻辑 return implode(',', $data); } // 反序列化:CSV字符串转数组 public function deserializeCsvArray(JsonDeserializationVisitor $visitor, string $csvString, array $type, Context $context) { // 可根据需求自定义CSV解析逻辑 return explode(',', $csvString); } }
完成后将该处理器注册到JMS序列化器即可:原生使用时调用$serializer->addSubscribingHandler(new CsvArrayHandler()),框架环境(如Symfony)给服务加上jms_serializer.subscribing_handler标签即可。
步骤2:给目标属性指定自定义类型
自有类(注解配置)
直接在属性的@JMS\Type注解中填写你自定义的类型名即可:
class OtherClass { /* * @JMS\Type("SomeClass") */ protected $someProperty; /* * @JMS\Type("array") // 走默认数组序列化规则 */ protected $serializeToDefaultArray; /* * @JMS\Type("csv_array") // 走自定义CSV序列化规则 */ protected $serializeToCSVString; }
第三方类(YAML配置)
不需要修改第三方类源码,直接在你的序列化YAML配置文件中给目标属性指定type即可:
# 第三方类序列化配置示例 ThirdParty\SomeClass: properties: # 走自定义CSV规则的属性 needCsvConvertField: type: csv_array # 走默认数组规则的属性 normalArrayField: type: array
扩展适配
如果需要实现字符串属性自动加密/编码,用完全相同的逻辑即可:自定义encrypted_string类型,在处理器的序列化方法中做加密、反序列化方法中做解密,仅给需要加密的字符串属性标注对应类型即可。
内容的提问来源于stack exchange,提问作者FLichter
相关产品推荐
相关产品推荐

