如何为基本类型创建 JMSSerialization 处理程序,例如数组 <-> csv 字符串

How to create a JMSSerialization Handler for for base types, e.g. array <-> csv string

如何为基本类型(如字符串或数组)创建自定义 JMSSerializen 处理程序?目标是以非默认方式(反)序列化 some 属性。例如,指定一个数组 属性 应该反序列化为 CSV 字符串而不是默认的 JSON 数组或一个字符串 属性 反序列化为加密/编码的字符串,等等。

虽然为自定义 class 创建这样的处理程序没问题,但我很难为基本类型做同样的事情。

class SyncableEntityHandler implements SubscribingHandlerInterface {

    public static function getSubscribingMethods() {
        return [
            [
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format' => 'json',
                'type' => 'SomeClass',
                'method' => 'serializeSomeClassToJson',
            ],
            [
                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                'format' => 'json',
                'type' => 'SomeClass',
                'method' => 'deserializeSomeClassFromJson',
            ],
        ];
    }

    public function serializeSomeClassToJson(JsonSerializationVisitor $visitor, AbstractSyncableEntity $entity, array $type, Context $context) {
        ...
    }

    public function deserializeSomeClassFromJson(JsonDeserializationVisitor $visitor, $entityGuid, array $type, Context $context) {
        ...
    }    
}


class OtherClass {
    /*
     * @JMS\Type("SomeClass")
     */
    protected $someProperty;

     /*
     * @JMS\Type("array")
     */
    protected $serializeToDefaultArray;

     /*
     * @JMS\Type("csv_array")    // How to do this?
     */
    protected $serializeToCSVString;
}

虽然我可以用 'type' => 'array' 创建一个处理程序来更改 所有 数组的(反)序列化,但我不知道只 select 一些个数组。

我已经考虑过使用 getterssetters(例如 getPropertyAsCsvString()setPropertyFromCsvString())。虽然这适用于自定义 classes,但我想序列化一些第三方 classes 以及我在 .yaml 文件中指定序列化选项而不是注释的地方。向这些 classes 添加 getter 和 setter 是不可能(容易)的。另外创建这些 getters 和 setter 会增加很多开销。

那么,有没有办法为某些属性创建和指定特殊处理程序?

实现非常简单:

class CsvArrayHandler implements SubscribingHandlerInterface {
    public static function getSubscribingMethods() {
        return [
            [
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format' => 'json',
                'type' => 'csv_array',
                'method' => 'serializeToJson',
            ],
            [
                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                'format' => 'json',
                'type' => 'csv_array',
                'method' => 'deserializeFromJson',
            ],
        ];
    }

    public function serializeSomeClassToJson(JsonSerializationVisitor $visitor, array $array, array $type, Context $context) {
        return implode(',', $array);
    }

    public function deserializeSomeClassFromJson(JsonDeserializationVisitor $visitor, string $csvString, array $type, Context $context) {
        return explode(',', $csvString);
    }
}

然后用 @JMS\Type("csv_array") 注释您的 属性 并注册处理程序。

请注意,使用 explodeimplode 不会转义输入,因此您可能需要使用 league/csv 之类的东西。