Skip to content
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

Can't get to work with DateTime denormalization #85

Open
ghostika opened this issue Jan 16, 2020 · 10 comments
Open

Can't get to work with DateTime denormalization #85

ghostika opened this issue Jan 16, 2020 · 10 comments
Labels

Comments

@ghostika
Copy link

I've used previously the 0.1.3 version and wanted to update it to v1. I've done the setup according to the documentation, just that 3 normalizer, but somehow my dateTime is not deserialized.
I've checked it with xdebug and all 3 normalizers are registered and they have the right order.

My json string:

[{"#type": "App\\Entity\\EventSchedule", "endDate": "2020-04-11T00:00:00+02:00", "startDate": "2020-01-07T00:00:00+01:00"}]

EventSchedule

class EventSchedule
{
    /**
     * Start date.
     *
     * @var DateTimeImmutable
     */
    private $startDate;

    /**
     * End date.
     *
     * @var DateTimeImmutable
     */
    private $endDate;
}

Error message:
Failed to denormalize attribute "endDate" value for class "App\Entity\EventSchedule": Expected argument of type "DateTimeImmutable", "string" given at property path "endDate"

I would highly appreciate any help.
I have ApiPlatform installed, but in this request, it's not used. I tried just calling the service in the controller and passing the string to the deserialize event.

@Toflar
Copy link
Contributor

Toflar commented Jan 16, 2020

Did you check the FAQ? https://github.com/dunglas/doctrine-json-odm#faq

@ghostika
Copy link
Author

Yes, that's what I meant with documentation. And the 3 normalizers, what are under the FAQ are registered.

@Toflar
Copy link
Contributor

Toflar commented Jan 16, 2020

Okay. So if you're using xdebug you should see if the datetime normalizer is called, right?

@ghostika
Copy link
Author

Yes, and that's the problem that it's not called but the DateTimeNormalizer is one of the 3 normalizers and I can't figure it out why.

@ghostika
Copy link
Author

ghostika commented Jan 16, 2020

I've taken a look at it again and I will try to create tomorrow an example SF app for this.
What I've found with XDebug that it finds the DateTimeDenormalizer and when it calls in the serializer the dernormalize methode, it calls the denormalize methode from Dunglas Serializer.
As the data is 2020-04-11T00:00:00+02:00 it skips the first if and not iterable, so skips the 2nd if and just simply returns the data, without a parent::denormalize call.

@ghostika
Copy link
Author

ghostika commented Jan 17, 2020

Ok, I know what the problem is and it's connected to my previous comment. I've found no update.MD file so I thought the old serialized data should be comatible with the new. I did a serialization and that is the result:

[{"#type": "App\\Entity\\Event\\EventSchedule", "endDate":{"#type":"DateTimeImmutable","#scalar":"2020-04-11T00:00:00+02:00"}, "startDate": {"#type":"DateTimeImmutable","#scalar":"2020-01-07T00:00:00+01:00"}}]

instead of the result in the DB with version 0.1.3

[{"#type": "App\\Entity\\EventSchedule", "endDate": "2020-04-11T00:00:00+02:00", "startDate": "2020-01-07T00:00:00+01:00"}]

I think this should be documented somewhere.

@ghostika
Copy link
Author

ghostika commented Feb 1, 2020

Or am I doing something wrong here @Toflar ?

@TNAJanssen
Copy link

TNAJanssen commented Mar 26, 2020

You can always use the compiler pass to add all the normalizers & encoders:

$container->addCompilerPass(new SerializerPass('dunglas_doctrine_json_odm.serializer'));

@TNAJanssen
Copy link

TNAJanssen commented Mar 26, 2020

@dunglas i changed the Symfony SerializerPass to work with your code, this will prevent these types of issues:

<?php

namespace App\Shared\Infrastructure\Symfony\Serializer;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;

class SerializerPass implements CompilerPassInterface
{
    use PriorityTaggedServiceTrait;

    private string $serializerService;
    private string $normalizerTag;
    private string $encoderTag;

    public function __construct(string $serializerService = 'dunglas_doctrine_json_odm.serializer', string $normalizerTag = 'serializer.normalizer', string $encoderTag = 'serializer.encoder')
    {
        $this->serializerService = $serializerService;
        $this->normalizerTag = $normalizerTag;
        $this->encoderTag = $encoderTag;
    }

    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition($this->serializerService)) {
            return;
        }

        if (!$normalizers = $this->findAndSortTaggedServices($this->normalizerTag, $container)) {
            throw new RuntimeException(sprintf('You must tag at least one service as "%s" to use the "%s" service.', $this->normalizerTag, $this->serializerService));
        }

        array_unshift($normalizers, new Reference('dunglas_doctrine_json_odm.normalizer.array'));
        $normalizers[] = new Reference('dunglas_doctrine_json_odm.normalizer.object');

        $serializerDefinition = $container->getDefinition($this->serializerService);
        $serializerDefinition->replaceArgument(0, $normalizers);

        if (!$encoders = $this->findAndSortTaggedServices($this->encoderTag, $container)) {
            throw new RuntimeException(sprintf('You must tag at least one service as "%s" to use the "%s" service.', $this->encoderTag, $this->serializerService));
        }

        $serializerDefinition->replaceArgument(1, $encoders);
    }
}

@ghostika
Copy link
Author

For me it was only 20 entries in the database, I just changed it with a script, but I think it would be good to mentions this difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants