Unable to override JMS Serializer's default handler for Symfony ConstraintViolationList
Asked Answered
D

3

3

I am unable to override default handlers in jms serializer bundle.

I'd like to change the way Symfony\Component\Validator\ConstraintViolationList is serialized so I wrote my own custom handler. And tagged it correctly as described in the documentation (and in various stackoverflow answers).

However, my handler keeps being overridden by the default handler for ConstraintViolationList that JMS Serializer bundle ships with.

I've tagged my handler service correctly. In fact, my handler service is detected and used correctly when I comment out ms_serializer.constraint_violation_handler service definition from vendor/jms/serializer-bundle/JMS/SerializerBundle/Resources/config/services.xml

How can I stop the default handler from overriding my custom one?

I've even tried overriding jms_serializer.constraint_violation_handler.class parameter from my own bundle but still no luck.

Here is my Handler class:

<?php
namespace Coanda\Bridge\JMSSerializer\Handler;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

class ConstraintViolationHandler implements SubscribingHandlerInterface
{
    public static function getSubscribingMethods()
    {
        $methods = [];
        $methods[] = [
            'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
            'type' => ConstraintViolationList::class,
            'format' => 'json',
            'method' => 'serializeListToJson'
        ];
        return $methods;
    }

    public function serializeListToJson(
        JsonSerializationVisitor $visitor,
        ConstraintViolationList $list,
        array $type,
        Context $context
    ) {
        $violations = [];
        foreach ($list as $item) {
            $violations[$item->getPropertyPath()][] = $item->getMessage();
        }
        if (null === $visitor->getRoot()) {
            $visitor->setRoot($violations);
        }
        return $violations;
    }

}

I've registered it in my services.xml

    <service id="coanda.serializer.constraint_violation_handler"
        class="Coanda\Bridge\JMSSerializer\Handler\ConstraintViolationHandler">
        <tag name="jms_serializer.subscribing_handler"
            type="Symfony\Component\Validator\ConstraintViolationList"
            direction="serialization" format="json" method="serializeListToJson" />
    </service>
Dullish answered 22/6, 2016 at 20:35 Comment(1)
I have the same case in symfony 5 and not undersatnd how to resolve itBiisk
D
4

This was happening because JMSSerializerBundle was registered after my bundle in AppKernel which meant that whatever service I define will be overridden by JMS Serializer's version of it.

Solution: put your bundle at the very bottom in AppKernel.php like so:

public function registerBundles()
{
    $bundles = [
        // .......
        new JMS\SerializerBundle\JMSSerializerBundle(),
        new My\Bundle\MyAwesomeBundle()
    ];

    return $bundles;
}
Dullish answered 29/6, 2016 at 11:2 Comment(0)
B
3

For versions

"name": "jms/serializer-bundle",
"version": "3.5.0",

"name": "symfony/framework-bundle",
"version": "v5.0.5",

decision should be like this, 'priority' => -915 should be in getSubscribingMethods

    /**
     * @return array
     */
    public static function getSubscribingMethods()
    {
        return [
            [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
                'format' => 'json',
                'type' => ConstraintViolationList::class,
                'method' => 'serializeCustomListToJson',
                'priority' => -915
            ]
        ];
    }

then \JMS\SerializerBundle\DependencyInjection\Compiler\CustomHandlersPass::sortAndFlattenHandlersList move it in last position and custom servce set in handler instead jms default handler

Biisk answered 1/4, 2020 at 14:23 Comment(1)
Should be enough to use priority: -1 (at least in v2 where default priority is 0).Soporific
P
0

this config work for me:

    exception:
        enabled: true
        serializer_error_renderer: true
Placet answered 20/12, 2021 at 17:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.