4

My entity FosUserBundle

namespace AppBundle\Entity;

use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\Exclude;
use JMS\Serializer\Annotation\ExclusionPolicy;

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use FOS\UserBundle\Model\Group;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 * @ExclusionPolicy("all")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @Exclude
     */
    protected $id;

    /**
     * @ORM\Column(type="integer")
     */
    private $balance = 0;

But if I try serialize App\Entity\User object:

$this->get('jms_serializer')->serialize($user, 'json');

It returned me ID field!

 {
  "id": 1,
  "username": "admin",
  "username_canonical": "admin",
  "email": "admin",
  "email_canonical": "admin",
  "enabled": true,
  "salt": "o12yxgxp3vkk0w4sck80408w8s8o84s",
  "password": "$2y$13$o12yxgxp3vkk0w4sck804uSVjSMSB1W0qwEjunGTHomBqqoGvkW9G",
  "last_login": "2016-02-28T17:28:19+0300",
  "locked": false,
  "expired": false,
  "roles": [
    "ROLE_ADMIN"
  ],
  "credentials_expired": false
}

2 Answers 2

8

Because of FOSUserBundle serializer rules, your exclusion strategies will not work.

To make your exclusion used, you need to tell JMSSerializer to squash the FOSUB serialisation.

In your config.yml, add the following:

jms_serializer:
    metadata:
        auto_detection: true # Don't forget this line
        directories:
            FOSUB:
                namespace_prefix: FOS\UserBundle
                path: %kernel.root_dir%/serializer/FOSUB

Then, create the file app/serializer/FOSUB/Model.User.yml and paste the following into:

FOS\UserBundle\Model\User:
    exclusion_policy: ALL

Now, all inherited properties are excluded, you can expose what you want.

Adapt it to your need if you want keep some properties, or redefine them in your entity.

See the corresponding issue #78.

Update

For your not working @Expose annotation, add the auto_detection like in my previous example.

If this doesn't solve the problem, use the @Groups annotation and do something like this :

use JMS\Serializer\Annotation\Groups;

/**
 * @ORM\Column(type="integer")
 * @JMS\Groups({"user"})
 */
private $balance = 0;

Change your controller like this:

use JMS\Serializer\SerializationContext;

$context = SerializationContext::create()->setGroups(array('user'));
$serializer->serialize($user, 'json', $context);

And it should works.

Keep in mind that this problem exists only because your User entity extends a class that already have serializer rules.

10
  • Thx!!! Okay and if I wanna seriallize settings for some entity class what I need do for that? I want to show balance field from AppBundle\Entity\User class... Feb 28, 2016 at 16:22
  • The config I given you disable the mapping of FOSUB, now the serialiser mapping of your own entity will be used, so you can use what you do actually to expose or exclude fields of your entity. You will maybe need to set auto_detection to true in the jms_serializer.metadata config
    – chalasr
    Feb 28, 2016 at 16:28
  • Just add the @Expose annotation on your field balance in your own class. All fields are excluded by default, just expose what you want using @expose, @groups and other strategies.
    – chalasr
    Feb 28, 2016 at 16:30
  • Don't forget that you can accept answer when your question is done, at your appreciation of course.
    – chalasr
    Feb 28, 2016 at 16:32
  • @Expose before $balance not working for me I add auto_detection is true in configuration Feb 28, 2016 at 16:45
0
        $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()),
        ]);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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