JMSSerializerBundle. нет контроля над метаданными третьих лиц

У меня есть две сущности, которые я хочу сериализовать с помощью JMSSerializerBundle. Объект Music имеет файл сопоставления с exclusion_policy: NONE.

Сущность Music имеет поле сущности User из FOSUserBundle. Сущность User имеет файл сопоставления с exclusion_policy: ALL с несколькими полями, установленными в expose: true, поэтому они будут сериализованы.

Проблема в том, что поле User полностью сериализуется. Неважно, если я изменю файл сопоставления объекта User.

Вот как это выглядит:

#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

Почему он не ссылается на свой собственный файл сопоставления? Или я где-то ошибаюсь?

Что я пробовал до сих пор

Я прочитал стороннюю документацию по метаданным. Он просто говорит добавить новый каталог в мою службу сериализатора. Я сделал это, но мне нужно расширить класс FOS\UserBundle\Entity, и у него также нет доступа к родительским защищенным полям, которые я пытаюсь исключить.


person tolgap    schedule 18.10.2012    source источник


Ответы (2)


Бьюсь об заклад, xxx\xxx\Entity\User: относится к вашему собственному пространству имен и классу.

Если да, то это неправильный способ.

Правила должны применяться к классу, в котором находятся свойства.

Учитывая свойство, которое вы указали в своей конфигурации, я предполагаю, что вы используете FOSUserBundle.

Поэтому вы должны применить свои правила к FOS\UserBundle\Model\User.

Затем вам нужно добавить конфигурацию JMSSerializer, чтобы указать, где находятся метаданные сериализатора для данного пространства имен.

Это должно выглядеть так:

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

В каталоге fos/ у вас должен быть Model.User.yml

Что-то вроде:

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]

Подробности:

При применении правил к сериализатору через метаданные сериализатор ищет свойство, которое объявлено внутри класса, который определен в метаданных.

Пример:

class Foo {
     protected $foo;
}

class Bar extends Foo {
     protected $bar;
}

Ваши метаданные будут выглядеть так:

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

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

ПРИМЕР НИЖЕ НЕ ПРАВИЛЬНЫЙ СПОСОБ СДЕЛАТЬ

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

если вы сделаете это, будут применяться (и отображаться) только правила для свойства bar.

person Boris Guéry    schedule 18.10.2012
comment
Итак, я могу удалить сопоставление для MyBundle/Entity/User, которое расширяет FOSUserBundle/Entity/User? - person tolgap; 18.10.2012
comment
ну, это зависит от вас, вам нужно удалить его, только если вы не пытаетесь применить правила к своей собственности. Если вы расширили пользовательскую модель/сущность и добавили свойства, вы должны сохранить их, но включить только те свойства, которые определены вашим собственным классом User. - person Boris Guéry; 18.10.2012
comment
@tolgap да, скорее всего, для каждой модификации, которую вы вносите в метаданные. - person Boris Guéry; 18.10.2012
comment
Позвольте мне внести ваши изменения, и если это сработает, я приму это для своего вопроса. - person tolgap; 18.10.2012
comment
Извините, что поднимаю призрак этого вопроса и ответа, но я заметил, что directories и auto_detection не работают вместе. Если я попытаюсь переопределить место, где JMS ищет сторонние метаданные, он не применит их. Но если я помещу те же самые метаданные в путь по умолчанию/ожидаемый и закомментирую конфигурацию каталога в jms_serializer, она будет применена. Я предполагаю, что они должны работать в тандеме? - person Sean Quinn; 14.09.2013
comment
Почему эта информация не может быть просто включена в официальные документы... мне потребовалось много времени, чтобы найти это - person Chris; 26.06.2015
comment
@Chris, не стесняйтесь пиариться ;) - person Boris Guéry; 30.06.2015
comment
Если я использую это, мне нужно также изменить все свои аннотации на конфигурации yaml? - person lony; 17.09.2015
comment
У меня были проблемы с исключением свойств из FOS\UserBundle\Model\User, и, наконец, я обнаружил, что вы должны определять свойства так, как они определены в классе User. Таким образом, $plainPassword и другие должны быть определены в yml с использованием camelCase. - person Genar; 20.01.2016

У меня была проблема, что я неправильно получал сериализатор. Вам нужно JMSSerializerBundle и используйте службу, чтобы конфигурация вступила в силу.

Итак, вместо:

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

Я использовал:

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

Использование первого способа загрузит вашу конфигурацию. Поскольку я использую Propel, мне нужно было игнорировать все поля BaseObject:

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

Обратите внимание, что BaseObject не имеет пространства имен, и для его работы вам потребуются следующие пакеты (глючили до метаданных 1.2):

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

Итак, я сделал этот файл:

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

и для определенных объектов (в пространстве имен модели) вам нужны файлы (с пространством имен по умолчанию как My/OtherBundle):

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

Примечание. Вам необходимо очистить кеш при создании новых файлов сериализатора.

person zebra    schedule 18.04.2013