Sylius: Unable to customize serialization policy

Created on 20 Sep 2017  路  12Comments  路  Source: Sylius/Sylius

Hi, guys!
I want to override Product serialization (for example, I want to change fields and add custom serialization group)
I've tried 2 ways to do this:

  1. I placed my custom serialization config in app/Resources/AdminApiBundle/config/serializer/Model.Product.yml:
Sylius\Component\Core\Model\Product:
    exclusion_policy: ALL
    xml_root_name: product
    properties:
        shortDescription:
            expose: true
            type: string
            groups: [Default, Detailed,MyCustomGroup]

And it has no effect

  1. I followed official JWT docs which describes how to override 3rd-party Metadata
jms_serializer:
    metadata:
        directories:
            sylius-core:
                namespace_prefix: "Sylius\\Component\\Core"
                path: "@AdminApiBundle/Resources/config/serializer"

And it also has no any effect

Is there any convenient way (and where is it documented) to solve this quite popular problem?

Documentation Stale

Most helpful comment

I'm afraid I have never made it work to override serializer config by just creating a file in app/Resources/AdminApiBundle/config/serializer/. But what you can do is to override the JMS config. But here you can have several problems.

  1. First of all, you have to be aware, that each config is related to the different namespace. And it will affect only fields from that namespace. So if you want to change a serialization of code property of Product you have to override config for sylius-product and path: "@ProductBundle/Resources/config/serializer". Overriding of the core will have no effect on a product. And otherwise.
  2. Secondly clear cache(or my personal advice, remove all cache folder) each time when you change something with serialization.
  3. Remember that, if you will change the config of the core serialization, for example, you have to copy and paste all serialization from the older folder.

For example, assuming that you want to override a core serialization in order to show ShortDescription

  • In app/config/config.yml at the end of the file:
jms_serializer:
    metadata:
        directories:
            sylius-core:
                namespace_prefix: "Sylius\\Component\\Core"
                path: ""%kernel.root_dir%//config/serializer/sylius-core/"
  • Create a new folders in app/config/: serializer and sylius-core inside of serializer folder
  • Copy and paste all configs from vendor/sylius/sylius/src/Sylius/Bundle/AdminApiBundle/Resources/config/serializer folder
  • Amend Model.Product.yml file with your config:
Sylius\Component\Core\Model\Product:
    exclusion_policy: ALL
    xml_root_name: product
    properties:
        shortDescription:
            expose: true
            type: string
            groups: [Default, Detailed,MyCustomGroup]
        averageRating:
            expose: true
            type: float
            groups: [Default, Detailed]
        images:
            expose: true
            type: array
            groups: [Default, Detailed]
        channels:
            expose: true
            type: array
            groups: [Detailed]
        reviews:
            expose: true
            type: array
            groups: [Detailed]
        productTaxons:
            expose: true
            type: array
            groups: [Detailed]
        mainTaxon:
            expose: true
            groups: [Detailed]
    relations:
        -   rel: self
            href:
                route: sylius_admin_api_product_show
                parameters:
                    code: expr(object.getCode())
                    version: 1
        -   rel: variants
            href:
                route: sylius_admin_api_product_variant_index
                parameters:
                    productCode: expr(object.getCode())
                    version: 1
            exclusion:
                groups: [Detailed]

  • clear cache
  • _et voil脿._ It should work now.

I will close this issue, as it is more a support request about JMS serializer rather than feature request or a bug in Sylius.

All 12 comments

I'm afraid I have never made it work to override serializer config by just creating a file in app/Resources/AdminApiBundle/config/serializer/. But what you can do is to override the JMS config. But here you can have several problems.

  1. First of all, you have to be aware, that each config is related to the different namespace. And it will affect only fields from that namespace. So if you want to change a serialization of code property of Product you have to override config for sylius-product and path: "@ProductBundle/Resources/config/serializer". Overriding of the core will have no effect on a product. And otherwise.
  2. Secondly clear cache(or my personal advice, remove all cache folder) each time when you change something with serialization.
  3. Remember that, if you will change the config of the core serialization, for example, you have to copy and paste all serialization from the older folder.

For example, assuming that you want to override a core serialization in order to show ShortDescription

  • In app/config/config.yml at the end of the file:
jms_serializer:
    metadata:
        directories:
            sylius-core:
                namespace_prefix: "Sylius\\Component\\Core"
                path: ""%kernel.root_dir%//config/serializer/sylius-core/"
  • Create a new folders in app/config/: serializer and sylius-core inside of serializer folder
  • Copy and paste all configs from vendor/sylius/sylius/src/Sylius/Bundle/AdminApiBundle/Resources/config/serializer folder
  • Amend Model.Product.yml file with your config:
Sylius\Component\Core\Model\Product:
    exclusion_policy: ALL
    xml_root_name: product
    properties:
        shortDescription:
            expose: true
            type: string
            groups: [Default, Detailed,MyCustomGroup]
        averageRating:
            expose: true
            type: float
            groups: [Default, Detailed]
        images:
            expose: true
            type: array
            groups: [Default, Detailed]
        channels:
            expose: true
            type: array
            groups: [Detailed]
        reviews:
            expose: true
            type: array
            groups: [Detailed]
        productTaxons:
            expose: true
            type: array
            groups: [Detailed]
        mainTaxon:
            expose: true
            groups: [Detailed]
    relations:
        -   rel: self
            href:
                route: sylius_admin_api_product_show
                parameters:
                    code: expr(object.getCode())
                    version: 1
        -   rel: variants
            href:
                route: sylius_admin_api_product_variant_index
                parameters:
                    productCode: expr(object.getCode())
                    version: 1
            exclusion:
                groups: [Detailed]

  • clear cache
  • _et voil脿._ It should work now.

I will close this issue, as it is more a support request about JMS serializer rather than feature request or a bug in Sylius.

Anyway, just a thought, maybe we should add some cookbook about it? It is not the first time we need to explain this. /cc @CoderMaggie

So we should keep it open and give the "Documentation Request" label :)

Ok :(

@lchrusciel , I think copying all the files from namespace_prefix to your app would not be good when upgrading sylius.
It's possible to avoid this if you manage to load your jms_serializer config before sylius.
We solved this by implementing prepend in our app bundle extension class.

@Snake-Tn sounds interesting, can you share some code?

@Snake-Tn Sounds like a very good solution, would be great if you can share a bit more. :)

Let's take as example : hide product id from product serialization.
We should achive this without being obliged to copy/past a bunch of serialization files.

  1. Tell jms_serializer to fetch serialization config for namespace prefix Sylius\\Component\\Product\\Model from your custom serialization config rather than from SyliusProductBundle , Do this by adding bellow code to your app/config/config.yml
jms_serializer:
    metadata:
        directories:
            custom-sylius-product:
                namespace_prefix: "Sylius\\Component\\Product\\Model"
                path: "@AppBundle/Resources/config/serializer"

Note that namespace_prefix should have the highest precision so you don't erase other configs.

  1. Implement an extension prepend in order to move the newly added jms_serialization config to the top.
    Do this by making your AppBundle/DependencyInjection/AppExtension implements PrependExtensionInterface
class AppExtension extends Extension implements PrependExtensionInterface
{
    public function load(array $configs, ContainerBuilder $container)
    {
...
    }

    public function prepend(ContainerBuilder $container)
    {
        foreach ($container->getExtensionConfig('jms_serializer') as $config) {
            foreach ($config['metadata']['directories'] as $directoryKey => $directoryConfig) {
                if (strpos($directoryKey, 'custom-sylius') === 0) {
                    $container->prependExtensionConfig('jms_serializer', $config);
                    continue;
                }
            }
        }
    }

}
  1. Create your custom jms config file named Model.Product.yml under @AppBundle/Resources/config/serializer folder.
Sylius\Component\Product\Model\Product:
    exclusion_policy: ALL
    xml_root_name: product
    properties:
        id:
            expose: false
            type: integer
            xml_attribute: true
            groups: [Default, Detailed, Autocomplete]
        code:
            expose: true
            type: string
            groups: [Default, Detailed, Autocomplete]
        options:
            expose: true
            type: array
            groups: [Default, Detailed]
        attributes:
            expose: true
            type: array
            groups: [Detailed]
        associations:
            expose: true
            type: array
            groups: [Detailed]
        translations:
            expose: true
            type: array
            groups: [Detailed]
    virtual_properties:
        getName:
            serialized_name: name
            groups: [Default, Detailed, Autocomplete]
    relations:
        -   rel: self
            href:
                route: sylius_admin_api_product_show
                parameters:
                    code: expr(object.getCode())
                    version: 1
        -   rel: variants
            href:
                route: sylius_admin_api_product_variant_index
                parameters:
                    productCode: expr(object.getCode())
                    version: 1
            exclusion:
                groups: [Detailed]

@pjedrzejewski , @venyii

Very nice! Maybe we can add it to our docs? /cc @CoderMaggie

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in a week if no further activity occurs. Thank you for your contributions.

i tried both solutions proposed in this issue, none of them seem to work for me

For other people that are trying to figure things out:
@lchrusciel said:

Secondly clear cache(or my personal advice, remove all cache folder) each time when you change something with serialization.

YES! Remove the folder, using console cache:clear won't work!

Was this page helpful?
0 / 5 - 0 ratings