JMSSerializerBundle. no control over third party meta data

13,888

Solution 1

I bet xxx\xxx\Entity\User: refers to your own namespace and class.

If it is, it is the wrong way to do.

The rules must be applied to the class where the properties live.

Given the property you exposed in your configuration, I guess you're using FOSUserBundle.

Therefore, you must apply your rules on FOS\UserBundle\Model\User.

Then you need to add a JMSSerializer config to indicate where the serializer metadata live for the given namespace.

It should look like:

jms_serializer:
  metadata:
    auto_detection: true
    directories:
      FOSUserBundle:
        namespace_prefix: "FOS\\UserBundle"
        path: "@YourUserBundle/Resources/config/serializer/fos"

In fos/ directory you should have Model.User.yml

With something like:

FOS\UserBundle\Model\User:
  exclusion_policy: ALL
  properties:
    id:
      expose: true
      groups: [list, details]
    username:
      expose: true
      groups: [details]
    email:
      expose: true
      groups: [me]
    roles:
      expose: true
      groups: [details]

Details:

When applying rules to the Serializer through metadata, the Serializer looks for the property which are declared inside the class which is defined in the Metadata.

Example:

class Foo {
     protected $foo;
}

class Bar extends Foo {
     protected $bar;
}

Your metadata will look like this:

Foo:
  exclusion_policy: ALL
  properties:
      foo: 
          expose: true

Bar:
  exclusion_policy: ALL
  properties:
      bar: 
          expose: true

THE EXAMPLE BELOW IS NOT THE CORRECT WAY TO DO

Bar:
  exclusion_policy: ALL
  properties:
      foo: 
          expose: true
      bar: 
          expose: true

if you do this, only the rules on the property bar will be applied (and exposed).

Solution 2

I had this problem that I was getting the serializer in a wrong way. You need JMSSerializerBundle and use the service for configuration to take effect.

So instead of:

//In controller we can use $this instead of $container
$serializer = $this->get('jms_serializer'); //JMSSerializerBundle

I used:

$serializer = SerializerBuilder::create()->build(); //JMSSerializer

Using the first way will load your configuration. Since I'm using Propel, I needed to ignore all BaseObject fields:

#app/config.yml
jms_serializer:
metadata:
    auto_detection: true
    directories:
        Propel:
            namespace_prefix: ""
            path: "@MySupporterBundle/Resources/config/serializer"

Note that BaseObject has no namespace and you need the following packages for this to work (bugged before metadata 1.2):

        "jms/serializer": "0.12.*",
        "jms/serializer-bundle" : "0.12.*@dev",
        "jms/metadata" : "1.3.*",

So I made this file:

#My/SupporterBundle/Resources/config/serializer/BaseObject.yml
BaseObject:
    exclusion_policy: ALL

and for specific objects(in Model namespace) you need files (with default namespace as My/OtherBundle):

My/OtherBundle/Resources/config/serializer/Model.om.BaseClass.yml My/OtherBundle/Resources/config/serializer/Model.Class.yml

Note: You need to clear cache when creating new serializer files

Share:
13,888

Related videos on Youtube

tolgap
Author by

tolgap

Updated on June 04, 2022

Comments

  • tolgap
    tolgap almost 2 years

    I have two entities I wish to serialize with the JMSSerializerBundle. The Music Entity has a mapping-file with exclusion_policy: NONE.

    The Music entity has a field of the entity User from FOSUserBundle. The User entity has a mapping-file with exclusion_policy: ALL with a few fields set to expose: true, so they will be serialized.

    The problem is, the User field gets fully serialized. It does not matter if I change the mapping-file of the User entity.

    This is how it looks:

    #My/Bundle/Resources/config/serializer/Entity.Music.yml
    xxx\xxx\Entity\Music:
        exclusion_policy: NONE
    
    #My/Bundle/Resources/config/serializer/Entity.User.yml
    xxx\xxx\Entity\User:
        exclusion_policy: ALL
        properties:
            id:
                expose: true
            username:
                expose: true
            username_canonical:
                exclude: true
            email:
                exclude: true
            email_canonical:
                exclude: true
            enabled:
                exclude: true
            salt:
                exclude: true
            password:
                exclude: true
            last_login:
                exclude: true
            confirmation_token:
                exclude: true
            password_requested_at:
                exclude: true
            groups:
                exclude: true
            locked:
                exclude: true
            expired:
                exclude: true
            expires_at:
                exclude: true
            roles:
                expose: true
            credentials_expired:
                exclude: true
            credentials_expired_at:
                exclude: true
    

    Why does it not refer to it's own mapping file? Or am I mistaken somewhere?

    What have I tried thusfar

    I have read the third party meta data documentation. It simply says to add a new directory in my serializer service. I have done that, but I have to extend the FOS\UserBundle\Entity class, and that also does not have access to the parent protected fields I'm trying to exclude.

  • tolgap
    tolgap over 11 years
    So I can remove the mapping for MyBundle/Entity/User which extends FOSUserBundle/Entity/User?
  • Boris Guéry
    Boris Guéry over 11 years
    well, it depends, you need to remove it only if you're not trying to apply rules on property of your own. If you extended the User Model/Entity and added properties, you should keep it but include only the property which are defined your own User class.
  • Boris Guéry
    Boris Guéry over 11 years
    @tolgap yeah most likely for every modification you make to the metadata.
  • tolgap
    tolgap over 11 years
    Let me do your modifications, and if it works I'll accept it for my question.
  • Sean Quinn
    Sean Quinn over 10 years
    Sorry to raise the specter of this question and answer, but I'm noticing that directories and auto_detection don't appear to work together. If I try to override the location where JMS looks for the third-party metadata, it won't apply it. But if I place that same metadata in the default/expected path and comment out the directory configuration in jms_serializer it does get applied. I'm assuming the two should work in tandem?
  • Chris
    Chris almost 9 years
    Why couldnt this information just be included in the official docs.... took me to long to find this
  • Boris Guéry
    Boris Guéry almost 9 years
    @Chris, feel free to make a PR ;)
  • lony
    lony over 8 years
    If I use this, do I have to change all my annotations to yaml configurations as well?
  • Genar
    Genar about 8 years
    I was having problems excluding properties from FOS\UserBundle\Model\User and finally I discovered you should define the properties as it is defined in User class. So $plainPassword and others should be defined in the yml using camelCase as well.