JMSSerializerBundle: @ExclusionPolicy("all") is not respected by the parent classes

I’m using the agnostic storage pattern for a bundle and I have three User classes:

Vendor\Bundle\AuthenticationBundle\Model\User
|- Vendor\Bundle\AuthenticationBundle\Entity\User
  |- Project\AuthenticationBundle\Entity\User

When using the @ExclusionPolicy("all") on the Project\AuthenticationBundle\Entity\User one would expect all properties of the parents to be also excluded. However, this is not the case and requires me to add the same exclusion policy on each parent, otherwise all the parent properties are serialized. This is a problem because I don’t want to create a dependency like this for the bundles.

The problem seems to lie in the way AnnotationDriver lists the class properties, since it doesn’t take into account the parent class annotations, if set.

Is there a workaround for this?

About this issue

  • Original URL
  • State: closed
  • Created 12 years ago
  • Comments: 33 (13 by maintainers)

Commits related to this issue

Most upvoted comments

I find this confusing as well. I override properties from the parent, and have a default policy of exclude all. I even tried an explicit exclusion on the overriden property, and it’s still exposed.

For example, I’m using the FOSUserBundle, and my extended user object is exposing groups, even though I have an annotation telling it to exclude it. It also means that password hashes are exposed because the ExclusionPolicy only applies to the child class.

Ideally a modification to ExclusionPolicy that allows excluding including parent would be ideal

Yes.

        $serializer = SerializerBuilder::create()
            ->setSerializationContextFactory(function () {
                return \JMS\Serializer\SerializationContext::create()
                    ->setSerializeNull(true)
                    ;
            })
            ->setDeserializationContextFactory(function () {
                return \JMS\Serializer\DeserializationContext::create()
                    ->setSerializeNull(true)
                    ;
            })
            ->setAnnotationReader($annotationReader)
            ->setPropertyNamingStrategy(new SerializedNameImportantThanPropertyNameStrategy())
            ->build();

Ignoring some parent classes: CComponent, CModel, CActiveRecord

        $class = new \ReflectionClass($serializer);
        $property = $class->getProperty('navigator');
        $property->setAccessible(true);
        $navigator = $property->getValue($serializer);

        $class = new \ReflectionClass($navigator);
        $property = $class->getProperty('metadataFactory');
        $property->setAccessible(true);
        $metadataFactory = $property->getValue($navigator);

        $class = new \ReflectionClass($metadataFactory);
        $property = $class->getProperty('loadedClassMetadata');
        $property->setAccessible(true);
        $property->setValue($metadataFactory, [
            'CComponent' => new NullMetadata(new \stdClass()),
            'CModel' => new NullMetadata(new \stdClass()),
            'CActiveRecord' => new NullMetadata(new \stdClass()),
        ]);

I can just confirm its really painful issue. Even if I add exclusion_policy: ALL and exclude: true in yml mapping for inherited property, serializer don’t respect those.

@johnpancoast

Is this library still being maintained?

yes https://github.com/schmittjoh/serializer/graphs/contributors

Would you accept a PR?

yes, only if it solves properly the problem (how to achieve this is not yet clear), it is backward compatible and has proper tests.

Regarding the “how”, I do not have any brilliant idea to do it. Some ideas:

  • Applying @ExclusionPolicy("all") on the parent is a BC break.
  • another solution might be @ExclusionPolicy("all", exludeFromParents={prop1, prop2,prop3}, includeFromParents={prop1, prop2,prop3})
  • allow @Exclude and @Expose at class level with a parameter, as example: @Exclude("useranme")
  • just use YAML or XML metadata definition
  • other?