#symfony #jmsserializerbundle
Вопрос:
Как создать пользовательский обработчик JMSSerializen для базовых типов, таких как строки или массивы? Целью было бы (де)сериализовать некоторые свойства не способами по умолчанию. Например, чтобы указать, что одно свойство массива должно быть десериализовано в строку CSV вместо массива JSON по умолчанию или одно строковое строковое свойство в зашифрованную / закодированную строку и т. Д.
Хотя создание такого обработчика для пользовательского класса не было проблемой, я с трудом делаю то же самое для базовых типов.
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 {
/*
* @JMSType("SomeClass")
*/
protected $someProperty;
/*
* @JMSType("array")
*/
protected $serializeToDefaultArray;
/*
* @JMSType("csv_array") // How to do this?
*/
protected $serializeToCSVString;
}
Хотя я могу создать обработчик 'type' => 'array'
для изменения (де)сериализации всех массивов, я не знаю, как выбрать только некоторые массивы.
Я уже думал об использовании getters
и setters
вместо этого (например getPropertyAsCsvString()
, и setPropertyFromCsvString()
). Хотя это будет работать с пользовательскими классами, я хотел бы также сериализовать некоторые сторонние классы, где я указываю параметры сериализации не с помощью аннотаций, а в .yaml
файлах. Добавление геттера и сеттеров в эти классы (нелегко) возможно. Кроме того, создание этих геттеров и сеттеров добавило бы много накладных расходов.
Итак, есть ли способ создать и указать специальные обработчики для некоторых свойств?
Ответ №1:
Реализация довольно проста:
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);
}
}
Затем просто отметьте свое свойство и зарегистрируйте обработчик. @JMSType("csv_array")
Обратите внимание, что использование explode
и implode
не исключает ввода, поэтому вместо этого вы можете использовать что-то вроде league/csv.