-
-
Notifications
You must be signed in to change notification settings - Fork 312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
possible to register a handler that will compare against abstract classes #577
Comments
Need to add an pre-serialize listener as: $serializer = SerializerBuilder::create()
->configureListeners(function(JMS\Serializer\EventDispatcher\EventDispatcher $dispatcher) {
$dispatcher->addListener('serializer.pre_serialize',
function(JMS\Serializer\EventDispatcher\PreSerializeEvent $event) {
if ($event->getObject() instanceof \MyCLabs\Enum\Enum){
$event->setType('MyCLabs\Enum\Enum');
}
}
)
})
->configureHandlers(function(HandlerRegistry $registry) {
$registry->registerHandler('serialization', 'MyCLabs\Enum\Enum', 'json',
function($visitor, Enum $object, array $type) {
return $object->getValue();
}
);
})
->build() |
thanks. Is there a way to match that with deserialization? I don't see a "PreDeserialization" method in the documentation at http://jmsyst.com/libs/serializer/master/reference/annotations#preserialize EDIT: found one by examining the |
okay @goetas , thought I had it but could probably use some pointers. When deserializing, I have $serializer = SerializerBuilder::create()
->configureListeners(function(EventDispatcher $dispatcher) {
$dispatcher->addListener(Events::PRE_DESERIALIZE,
function(PreDeserializeEvent $event) {
if (is_a($event->getType()['name'], 'MyClabs\Enum\Enum', true)) {
$event->setType('MyClabs\Enum\Enum');
}
}
);
})
->configureHandlers(function(HandlerRegistry $registry) {
$registry->registerHandler('deserialization', 'MyClabs\Enum\Enum', 'json',
function(VisitorInterface $visitor, $value, array $class) {
return new $class['name']($value);
}
);
})
->build()
; however by Setting the type on the pre-deserialize event, it tries to instantiate a base class of How can I add a deserialization handler for instantiating enumerators, but use the same theory that I only need to apply it once on an abstract class? |
Different problems have different solutions, different drawbacks and different advantages. For my current understanding of your usecase, you can do something as:
namespace App\Enums
use MyCLabs\Enum\Enum;
class UserType extends Enum
{
// something....
}
class User
{
/** @Type("MyCLabsEnums<'App\Enums\UserType'>") */
private $type;
} I will configure the serializer in this way:: $serializer = SerializerBuilder::create()
->configureHandlers(function(HandlerRegistry $registry) {
// this handles serialization
$registry->registerHandler('serialization', 'MyCLabsEnums', 'json',
function($visitor, Enum $object, array $type) {
return $object->getValue();
}
);
// this handles deserialization
$registry->registerHandler('deserialization', 'MyCLabsEnums', 'json',
function($visitor, $data, array $type) {
$class = $type['params'][0];
return new $class($data);
}
);
})
->build() this approach is faster and simpler than having listeners (and works for serialization and deserialization), but requires you to set the type of properties for each domain class. |
@goetas I forgot to come back and thank you. One last question for you. While I can specify a custom handler for a given object type, is there a way I can specify an array of those? something similar to /** @Type("array<MyCLabsEnums<'App\Enums\UserType'>>") */
private $type; I know I can create a listener for an array type, and use |
an array of "handlers" with the current featureset available in the serializer is not possible and makes no sense. the main reason is that you will need some logic to decide which handler needs to be triggered. Currently there is no "skip-handler" feature, so the first handler has to "handle" the process (or the forward it to an another handler) |
I might have mis-phrased it. If you have a property that stores a single object, which you want to use a custom handler instead of the object itself, that can be defined as /**
* @var App\Enums\UserType
* @Type("MyCLabsEnums<'App\Enums\UserType'>")
*/ which will use the If you have a property that stores an array of those values, like the below, how would the type declaration work that each entity of the array is an object that is processed through the handler. /*
* @var App\Enums\UserType[]
* @Type(?)
*/ |
so I'm using
MyClabs\Enum\Enum
to store enumerators in my classes.the problem I'm running into is that if I register a handler like so
serializer doesn't actually intercept them, since the full Class Name doesn't match, even though they all share the same abstract class. While I know I can add a separate handler for each individual enumerator, I'd rather not, as this adds extra maintenance on future scoping.
Is there another way to have serialization listen or interact with objects that have properties of an abstract class?
The text was updated successfully, but these errors were encountered: