Search code examples
phpjsonsymfonyserializationdoctrine

Symfony2 custom json serialization


I am wondering how I can personify the default JSON serialization with JMS on entities.

I have an object A that have a OneToMany relation with an object B.
I expose the object B and attrA from A object.

But instead of having the basic JSON

{'attrA' : 'foo', 'Bs' : {{'attrB' : 'bar'}, {'attrB' : 'baz'}, ...} }

I want to have

{'attrA' : 'foo', 'Bs' : {'bar', 'baz', ...}}

Is it possible to do that?


Solution

  • A way to do this, is to play with serializer's annotations

    I assume your value objects looks like this

    class Foo
    {
        /**
         * @var string
         */
        private $attrA;
    
        /**
         * @var ArrayCollection<Bar>
         */
        private $bs;
    }
    
    class Bar
    {
        /**
         * @var string
         */
        private $attrB;
    }
    

    Import annotations

    First, if you didn't already, you need to import the annotations at the top of your files

    use JMS\Serializer\Annotation as Serializer;
    

    Set up a custom getter

    By default, JMS serializer gets the property value through reflection. My thoughts go on creating a custom accessor for the serialization.
    Note: I assume your bs property is an ArrayCollection. If not, you can use array_map

    // Foo.php
    
    /**
     * @Serializer\Accessor(getter="getBarArray")
     */
    private $bs;
    
    /**
     * @return ArrayCollection<string>
     */
    public function getBarArray()
    {
        return $this->getBs()->map(function (Bar $bar) {
            return $bar->getAttrB();
        });
    }
    

    Setting up a custom Accessor(getter) will force the serializer to use the getter instead of the reflection. This way, you can tweak any property value to get it in the format you want.

    Result

    Serialization of these value objects would result in

    {'attrA' : 'foo', 'Bs' : ['bar', 'baz', ...]}