Skip to content

Instantly share code, notes, and snippets.

@Aliance
Created May 21, 2020 22:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aliance/9bb8ce4b93254bc214cf5564779464e2 to your computer and use it in GitHub Desktop.
Save Aliance/9bb8ce4b93254bc214cf5564779464e2 to your computer and use it in GitHub Desktop.
Add extra information for the list of objects while serializing via JMS
<?php
declare(strict_types=1);
namespace AppBundle\DTO;
use AppBundle\Entity\Item;
use JMS\Serializer\Annotation as JMS;
/**
* @JMS\ExclusionPolicy("all")
*/
class ItemListDTO
{
/**
* @JMS\Expose
* @JMS\Type("array<AppBundle\Entity\Item>")
*/
private array $items;
public function __construct(array $items)
{
$this->items = $items;
}
/**
* @return Item[]
*/
public function getItems(): array
{
return $this->items;
}
}
<?php
declare(strict_types=1);
namespace AppBundle\Entity;
use JMS\Serializer\Annotation as JMS;
/**
* @JMS\ExclusionPolicy("all")
*/
class Item
{
/**
* @JMS\Expose
* @JMS\Type("integer")
*/
private ?int $id = null;
/**
* @JMS\Expose
* @JMS\Type("string")
*/
private ?string $title = null;
}
<?php
declare(strict_types=1);
namespace AppBundle\Listener;
use AppBundle\DTO\ItemListDTO;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
class ItemListSubscribingHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods(): array
{
return [
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => ItemListDTO::class,
/** @see ItemListSubscribingHandler::serializeItemListToJson() */
'method' => 'serializeItemListToJson',
],
];
}
public function serializeItemListToJson(
JsonSerializationVisitor $visitor,
ItemListDTO $itemList,
array $type,
Context $context
) {
return $itemList->getItems();
}
}
<?php
declare(strict_types=1);
namespace AppBundle\Listener;
use AppBundle\DTO\ItemListDTO;
use AppBundle\Entity\Item;
use JMS\Serializer\Context;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
class ItemSerializationSubscriber implements EventSubscriberInterface
{
private array $extraDataList;
public static function getSubscribedEvents(): array
{
return [
[
'event' => Events::PRE_SERIALIZE,
/** @see ItemSerializationSubscriber::onItemListPreSerialize() */
'method' => 'onItemListPreSerialize',
'class' => ItemListDTO::class,
],
[
'event' => Events::POST_SERIALIZE,
/** @see ItemSerializationSubscriber::onPostSerialize() */
'method' => 'onPostSerialize',
'class' => Item::class,
],
];
}
public function onItemListPreSerialize(ObjectEvent $event): void
{
$visitor = $event->getVisitor();
if (!$visitor instanceof JsonSerializationVisitor) {
return;
}
$itemList = $event->getObject();
if (!$itemList instanceof ItemListDTO) {
return;
}
$itemIdList = array_map(fn (Item $item) => $item->getId(), $itemList->getItems());
$this->extraDataList = $this->statsService->getItemSize($itemIdList);
}
public function onPostSerialize(ObjectEvent $event): void
{
$visitor = $event->getVisitor();
if (!$visitor instanceof JsonSerializationVisitor) {
return;
}
$item = $event->getObject();
if (!$item instanceof Item) {
return;
}
$itemId = $item->getId();
$extraData = $this->extraDataList[$itemId] ?? null;
$context = $event->getContext();
$visitor->visitProperty(new StaticPropertyMetadata('', 'extra', $extraData), $extraData, $context);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment