How to create a good hypermedia format using JMSSerializerBundle?
Asked Answered
Y

1

49

Lets say I want to create an XML-response that will looks something like the following:

<?xml version="1.0" encoding="utf‐8"?>
<product xmlns="urn:com.acme.prods" xmlns:atom="http://www.w3.org/2005/xlink">
  <id>1234</id>
  <name>Red Stapler</name>
  <price currency="EUR">3.14</price>
  <atom:link rel="payment" type="application/com.acme.shop+xml"
             href="http://acme.com/products/1234/payment" />
</product>

Given an domain model that looks something like the following:

<?php
// Product.php
namespace Acme\Bundle\ProductBundle\Entity;
use Acme\Bundle\ProductBundle\Money\Money;

class Product
{
  /**
   * @var integer
   */
  private $id;

  /**
   * @var string
   */
  private $name;

  /**
   * @var Money
   */
  private $price;

  [..]
}

And a money-class along the lines of:

<?php
// Money.php
namespace Acme\Bundle\ProductBundle\Money;

class Money
{
  /**
   * @var string
   */
  private $currency;
  /**
   *
   */
  private $amount;
}

Now, to my questions. It would be pretty simple to create a response that looks like the following

<?xml version="1.0" encoding="utf‐8"?>
<product>
  <id>1234</id>
  <name>Red Stapler</name>
  <price currency="EUR">3.14</price>
</product>

using either annotations, XML or YAML to tell JMSSerializerBundle how to serialize the Product-object. However, the xmlns:atom and <atom:link> entries should not be specified by the entity, since it should have no concept of how and where it is located. You could also imagine more links with different rel-attributes, such as edit.
One solution that comes to mind would be a service that listens to serialization events for specific objects, and adds these attributes and tags as appropriate. The service could use DI to get hold of the Request, Router-service etc to generate these links in a format that is suitable for the requested format. I.E in an XML-response, it could set the appropriate type to application/media-format+xml, whereas in a json-response, it could generate something like

"links": [
   {
     "rel": "payment", 
     "type": "application/media-format+json", 
     "href": "[...]"
   }
]

Now, in the documentation for JMSSerializerBundle, I find annotations for @PreSerialize, and @PostSerialize, but they seem to only be able to call methods on the object being serialized.
Does anyone know how/if this can be achieved? Or do I have to use a templating engine such as Twig and manually create the XML-response?

Yahairayahata answered 13/9, 2012 at 13:15 Comment(2)
Very interesting question. After poking a bit around, I thing there is no other solution then polluting your entity with additional attributes used only for the serialization... What appears to be missing in the bundle is a possibility to handle the complete serialization of a particular object with another class.Ruel
[You can Check Here 1: specify-group-per-attribute ][1] [Also here 2: jms serializer bundle-complex-generated-value][2] [1]: #13665869 [2]: #14475671Idaidae
S
3

The Serializer Bundle alone might not be enough for this situation as it is only concerned with serialization and deserialization, not more complex semantical tasks.

I would suggest looking into FSCHateoasBundle to implement a pretty hypermedia format for your API.

Shellyshelman answered 25/11, 2012 at 16:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.