Created
March 28, 2018 13:28
-
-
Save joshlopes/7aa196bf5108877e1f0c0c67224d39aa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Bridge\Symfony\Serializer; | |
use App\Serializer\ModelDenormalizeInterface; | |
use App\Serializer\ModelNormalizerInterface; | |
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer as SymfonyObjectNormalizer; | |
/** | |
* Decorate Symfony object normalizer with a set of rules | |
* | |
* Important notes: | |
* - You will never serialise / deserialize multiple times in the same cycle | |
* - You will never use custom serialization callbacks for the same property name cross objects | |
* | |
* This custom normalizer will: | |
* - [normalize] remove all empty and null values from the models properties | |
* - [normalize] set callbacks based on the model (Note: if the same property name is given it will override) | |
* - [denormalize] set callbacks based on the model denormalize method (Needs to be implementing the ModelDenormalizationInterface) | |
* - [denormalize] when preparing the data a set of callbacks will also be taken in consideration | |
*/ | |
class CustomNormalizer extends SymfonyObjectNormalizer | |
{ | |
public function normalize($object, $format = null, array $context = []) | |
{ | |
if ($object instanceof ModelNormalizerInterface) { | |
// can bring some conflicts | |
$this->callbacks = array_merge($this->callbacks, $object->normalize()); | |
} | |
$data = parent::normalize($object, $format, $context); | |
// remove every "null" / empty value | |
return array_filter($data, function ($value) { | |
return null !== $value; | |
}); | |
} | |
public function denormalize($data, $class, $format = null, array $context = []) | |
{ | |
if (\in_array(ModelDenormalizeInterface::class, class_implements($class), true)) { | |
/** @var ModelDenormalizeInterface $object */ | |
$object = new $class(); | |
$this->callbacks = array_merge($this->callbacks, $object->denormalize()); | |
} | |
return parent::denormalize($data, $class, $format, $context); | |
} | |
/** | |
* Decorate the function so we can run the callbacks define | |
* for denormalization / preparing the data for the setters | |
* | |
* This function is only invoked before denormalizing the data | |
*/ | |
public function prepareForDenormalization($data): array | |
{ | |
$data = parent::prepareForDenormalization($data); | |
foreach ($this->callbacks as $property => $callback) { | |
if (isset($data[$property])) { | |
$data[$property] = $callback($data[$property], $data); | |
} | |
} | |
return $data; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment