The Symfony Serializer component is used to turn PHP objects into a specific format (XML, JSON, YAML, ...) and the other way around. In order to maintain its simplicity, we've limited the scope of the component and that's why it's one of the Symfony components with less new features since its introduction.
In Symfony 2.7 we've decided to reverse this trend and we're introducing a new feature to serialize/deserialize different sets of object attributes. Consider the following object that includes properties aimed to administrators, affiliates and regular users:
1 2 3 4 5 6 7 8 9 10 11
class Product
{
// this property is exclusive for administrators
public $itemsSold;
// this property is visible by administrators and affiliates
public $commission;
// this property is visible by all (administrators, affiliates, users)
public $price;
}
The definition of serialization can be specified using annotations, XML or YAML. In case of using annotations, define serialization groups as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use Symfony\Component\Serializer\Annotation\Groups;
class Product
{
/**
* @Groups({"admins"})
*/
public $itemsSold;
/**
* @Groups({"admins", "affiliates"})
*/
public $commission;
/**
* @Groups({"admins", "affiliates", "users"})
*/
public $price;
}
Now that serialization groups have been defined, you can serialize only the attributes that belong to the given groups:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Doctrine\Common\Annotations\AnnotationReader;
$product = new Product();
$product->itemsSold = 20;
$product->commission = 7.5;
$product->price = 19.99;
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new PropertyNormalizer($classMetadataFactory);
$serializer = new Serializer([$normalizer]);
$data = $serializer->normalize($product, null, ['groups' => ['admins']]);
// $data = ['itemsSold' => 20, 'commission' => 7.5, 'price' => 19.99];
$data = $serializer->normalize($product, null, ['groups' => ['affiliates']]);
// $data = ['comission' => 7.5, 'price' => 19.99];
$data = $serializer->normalize($product, null, ['groups' => ['users']]);
// $data = ['price' => 19.99];
$data = $serializer->normalize($product, null, ['groups' => ['affiliates', 'users']]);
// $data = ['commission' => 7.5, 'price' => 19.99];
Similarly, you can define the groups to user when deserializing contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Doctrine\Common\Annotations\AnnotationReader;
$product = new Product();
$product->itemsSold = 20;
$product->commission = 7.5;
$product->price = 19.99;
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new PropertyNormalizer($classMetadataFactory);
$serializer = new Serializer(array($normalizer));
$product = $serializer->denormalize(
['itemsSold' => 20, 'price' => 19.99, 'commission' => 7.5],
'Product',
null,
['groups' => ['affiliates', 'users']]
);
// $product = Product(price: 19.99, commission: 7.5)
Awesome! Looks like JMSSerializer is not so necessary now, thanks Kévin.
There are a few issues in your code snippets:
One more issue : serializing attributes 'affiliates' and 'users' group will only produce this : // $data = ['commission' => 7.5, 'price' => 19.99]; (This in the exemple of serializing. The exemple of deserialization is correct)
@Christophe @cgodot thanks for your review! All issues have been fixed now.
Another thing,the following use statement must be added to the Product class snippet:
Wonderful !
Good news !
This PR also introduce support for of the "ignoring attributes" feature for deserialization (for serialization, the feature was available since Symfony 2.3): http://symfony.com/doc/current/components/serializer.html#ignoring-attributes-when-serializing