0

I have two modules, each of which is defining a normalizer service

module_one.services.yml

services:
  module_one.normalizer.node_entity:
    class: Drupal\module_one\Normalizer\ModuleOneEntityNormalizer
    arguments: ['@entity_type.manager']
    tags:
      - { name: normalizer, priority: 10 }

module_two.services.yml

services:
  module_two.normalizer.node_entity:
    class: Drupal\module_two\Normalizer\ModuleTwoEntityNormalizer
    arguments: ['@entity_type.manager']
    tags:
      - { name: normalizer, priority: 10 }

For each module, I am creating a distinct normalizer and presumably defining a separate namespace, ex:

<?php

namespace Drupal\module_one\Normalizer;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\serialization\Normalizer\ContentEntityNormalizer;
use Drupal\node\NodeInterface;

/**
 * Converts the Drupal entity object structures to a normalized array.
 */
class ModuleOneEntityNormalizer extends ContentEntityNormalizer {
...

The problem is that with both modules enabled, one service is blocking the other - the serializer / normalizer fires as expected for the first one but not for the second. The only way to get the other one to be recognized is to increase its priority but that blocks the first.

What am I missing in the definitions that would prevent these two services from conflicting with each other?

Update: Thanks for the really helpful comments, starting to dial in on this. Both normalizers have the same protected $supportedInterface, ex:

  /**
   * The interface or class that this Normalizer supports.
   *
   * @var string
   */
  protected $supportedInterfaceOrClass = [
    'Drupal\node\NodeInterface'
  ];

Which is flagged in the Drupal Serialization API handbook as an issue

3
  • 2
    Why not change the priority and then adjust its selection rules as to when its applicable? api.drupal.org/api/drupal/… if they operate on the same exact entity types with no conditional differences, you likely need to add context information when serializing.
    – Kevin
    Oct 13 at 15:27
  • 2
    Or maybe a decorator service
    – Hudri
    Oct 13 at 15:30
  • 3
    You need to clarify what is in protected $supportedInterfaceOrClass. If it's the same, what other parameter if not the priority or format selects which normalizer should be used?
    – 4k4
    Oct 13 at 15:51
1

Found a working answer with the helpful guidance from the comments here. The key is that in both Normalizer classes, I was not using the supportsNormalization function

 /**
 * Checks whether the given class is supported for normalization by this normalizer.
 */
   public function supportsNormalization($data, $format = NULL) {
      if (!is_object($data) || !$this->checkFormat($format)) {
        return FALSE;
      }
      if ($data instanceof NodeInterface && $data->getType() == 'myContentType') {
        return TRUE;
      }
        return FALSE;
      }
    }

With the above function, I can continue to have the priority for both normalizers in the services.yml set to the same value (ex. '10'), it will fire for both but return false if it doesn't match the particular content type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.