How to create a custom JMSSerializen handler for base types like strings or arrays? The goal would be to (de)serialize some properties in non-default ways. For example to specify that one array property should be deserialized to a CSV string instead to a default JSON array or one string string property to to an encrypted / encoded string, etc.
While creating such a handler for a custom class was no problem, I struggle to do the same for base types.
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;
}
While I can create a handler with 'type' => 'array'
to change the (de)serializiation of all arrays, I do not know to only select some arrays.
I already thought about using getters
and setters
instead (e.g. getPropertyAsCsvString()
and setPropertyFromCsvString()
). While this would work with custom classes, I would like to serialize some third-party classes as well where I specify the serialization options not with annotations but in .yaml
files. Adding getter and setters to these classes is not (easily) possible. Additionally creating these getters and setters would add a lot of overhead.
So, is there a way to create and specify special handlers for some properties?
The implementation is quite straightforward:
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);
}
}
Then just annotate your property with @JMS\Type("csv_array")
and register the handler.
Note that using explode
and implode
does not escape the input so you may want to use something like league/csv instead.