Search code examples
phpsymfonydoctrine-ormjms-serializer

Force JMS Serialiser to output an object keyed by a specific field


I have an entity Product with a one-to-many relationship to an entity Property. When I serialise a product instance using the JMS Serialiser I get the following JSON output:

{
    "id": 123,
    "name": "Mankini Thong",
    "properties": [{
        "label": "Minimal size",
        "name": "min_size",
        "value": "S"
    }, {
        "label": "Maximum size",
        "name": "max_size",
        "value": "XXXL"
    }, {
        "label": "colour",
        "name": "Colour",
        "value": "Office Green"
    }]
}

I try to get the serialiser to serialise the properties collection as an object in which a certain field is used as key. For instance, the name field. The desired output is:

{
    "id": 123,
    "name": "Mankini Thong",
    "properties": {
        "min_size": {
            "label": "Minimal size",
            "value": "S"
        }, 
        "max_size": {
            "label": "Maximum size",
            "value": "XXXL"
        }, 
        "colour": {
            "label": "Colour",
            "value": "Office Green"
        }
    }
}

What would be the best approach to achieve this?


Solution

  • Ok, I figured it out:

    First add a virtual property to the serialisation mapping and exclude the original properties field. My configuration is in yaml but using annotations shouldn't be that different:

    properties:
        properties:
            exclude: true
    virtual_properties:
        getKeyedProperties:
            serialized_name: properties
            type: array<Foo\BarBundle\Document\Property>
    

    Then I've added the getKeyedProperties method to the document class in Foo\BarBundle\Document\Article:

    /**
     * Get properties keyed by name
     *
     * Use the following annotations in case you defined your mapping using
     * annotations instead of a Yaml or Xml file:
     *
     * @Serializer\VirtualProperty
     * @Serializer\SerializedName("properties")
     *
     * @return array
     */
    public function getKeyedProperties()
    {
        $results = [];
    
        foreach ($this->getProperties() as $property) {
            $results[$property->getName()] = $property;
        }
    
        return $results;
    }
    

    Now, the serialised output contains an object properties which are serialised article properties keyed by name.