SerializeAs annotation
This commit is contained in:
parent
02776c4c90
commit
2c9a795756
@ -69,14 +69,10 @@ services:
|
||||
ProxyManager\Configuration: '@proxy.config'
|
||||
|
||||
# serializer configuration
|
||||
serializer.datetime_normalizer:
|
||||
class: Symfony\Component\Serializer\Normalizer\DateTimeNormalizer
|
||||
arguments: [!php/const DateTime::ATOM]
|
||||
tags: [serializer.normalizer]
|
||||
App\Service\SerializerContextFactory:
|
||||
arguments:
|
||||
$factory: '@jms_serializer.metadata_factory'
|
||||
|
||||
App\Service\Normalizer\:
|
||||
resource: '../src/Service/Normalizer'
|
||||
tags: [serializer.normalizer]
|
||||
|
||||
# other servces
|
||||
App\Service\ProviderResolver:
|
||||
|
@ -7,6 +7,7 @@ use App\Controller\Controller;
|
||||
use App\Model\Departure;
|
||||
use App\Provider\DepartureRepository;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Service\SerializerContextFactory;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -68,6 +69,11 @@ class DeparturesController extends Controller
|
||||
->flatMap(ref([ $departures, 'getForStop' ]))
|
||||
->sortBy(property('departure'));
|
||||
|
||||
return $this->json($stops->values()->slice(0, (int)$request->query->get('limit', 8)));
|
||||
return $this->json(
|
||||
$stops->values()->slice(0, (int)$request->query->get('limit', 8)),
|
||||
200,
|
||||
[],
|
||||
$this->serializerContextFactory->create(Departure::class, ['Default'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,21 +4,24 @@
|
||||
namespace App\Controller;
|
||||
|
||||
|
||||
use App\Service\SerializerContextFactory;
|
||||
use JMS\Serializer\SerializerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller as SymfonyController;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
abstract class Controller extends SymfonyController
|
||||
abstract class Controller extends AbstractController
|
||||
{
|
||||
private $serializer;
|
||||
protected $serializer;
|
||||
protected $serializerContextFactory;
|
||||
|
||||
public function __construct(SerializerInterface $serializer)
|
||||
public function __construct(SerializerInterface $serializer, SerializerContextFactory $serializerContextFactory)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
$this->serializerContextFactory = $serializerContextFactory;
|
||||
}
|
||||
|
||||
protected function json($data, int $status = 200, array $headers = [], array $context = []): JsonResponse
|
||||
protected function json($data, int $status = 200, array $headers = [], $context = null): JsonResponse
|
||||
{
|
||||
return new JsonResponse($this->serializer->serialize($data, "json"), $status, $headers, true);
|
||||
return new JsonResponse($this->serializer->serialize($data, "json", $context), $status, $headers, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use App\Serialization\SerializeAs;
|
||||
use Carbon\Carbon;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
@ -22,11 +23,30 @@ class Departure implements Fillable
|
||||
* Information about line.
|
||||
* @var Line
|
||||
* @Serializer\Type(Line::class)
|
||||
* @SerializeAs({"Default": "Default"})
|
||||
* @SWG\Property(ref=@Model(type=Line::class, groups={"Default"}))
|
||||
*
|
||||
*/
|
||||
private $line;
|
||||
|
||||
/**
|
||||
* Information about line.
|
||||
* @var Track|null
|
||||
* @Serializer\Type(Track::class)
|
||||
* @SerializeAs({"Default": "Identity"})
|
||||
* @SWG\Property(ref=@Model(type=Track::class, groups={"Identity"}))
|
||||
*/
|
||||
private $track;
|
||||
|
||||
/**
|
||||
* Information about line.
|
||||
* @var Trip|null
|
||||
* @Serializer\Type(Trip::class)
|
||||
* @SerializeAs({"Default": "Identity"})
|
||||
* @SWG\Property(ref=@Model(type=Trip::class, groups={"Identity"}))
|
||||
*/
|
||||
private $trip;
|
||||
|
||||
/**
|
||||
* Information about stop.
|
||||
* @var Stop
|
||||
@ -140,6 +160,26 @@ class Departure implements Fillable
|
||||
$this->stop = $stop;
|
||||
}
|
||||
|
||||
public function getTrack(): ?Track
|
||||
{
|
||||
return $this->track;
|
||||
}
|
||||
|
||||
public function setTrack(?Track $track): void
|
||||
{
|
||||
$this->track = $track;
|
||||
}
|
||||
|
||||
public function getTrip(): ?Trip
|
||||
{
|
||||
return $this->trip;
|
||||
}
|
||||
|
||||
public function setTrip(?Trip $trip): void
|
||||
{
|
||||
$this->trip = $trip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Serializer\VirtualProperty()
|
||||
* @Serializer\Type("int")
|
||||
|
@ -53,7 +53,9 @@ class GenericScheduleRepository extends DatabaseRepository implements ScheduleRe
|
||||
]);
|
||||
|
||||
return $schedule->map(function (TripStopEntity $entity) use ($stop) {
|
||||
$line = $entity->getTrip()->getTrack()->getLine();
|
||||
$trip = $entity->getTrip();
|
||||
$track = $trip->getTrack();
|
||||
$line = $track->getLine();
|
||||
/** @var StopEntity $last */
|
||||
$last = $entity->getTrip()->getTrack()->getStopsInTrack()->last()->getStop();
|
||||
|
||||
@ -63,6 +65,8 @@ class GenericScheduleRepository extends DatabaseRepository implements ScheduleRe
|
||||
'stop' => $stop,
|
||||
'display' => $last->getName(),
|
||||
'line' => $this->convert($line),
|
||||
'track' => $this->convert($track),
|
||||
'trip' => $this->convert($trip),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
@ -129,6 +129,8 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
|
||||
|
||||
$departure = clone $real;
|
||||
$departure->setDisplay($scheduled->getDisplay());
|
||||
$departure->setTrack($scheduled->getTrack());
|
||||
$departure->setTrip($scheduled->getTrip());
|
||||
|
||||
return $departure;
|
||||
}
|
||||
|
15
src/Serialization/SerializeAs.php
Normal file
15
src/Serialization/SerializeAs.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Serialization;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY","METHOD","ANNOTATION"})
|
||||
*/
|
||||
class SerializeAs
|
||||
{
|
||||
/** @var array<string, string> @Required() */
|
||||
public $map;
|
||||
}
|
79
src/Service/SerializerContextFactory.php
Normal file
79
src/Service/SerializerContextFactory.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Serialization\SerializeAs;
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
use JMS\Serializer\Metadata\PropertyMetadata;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
use Metadata\AdvancedMetadataFactoryInterface;
|
||||
use Metadata\ClassHierarchyMetadata;
|
||||
use function Kadet\Functional\Transforms\property;
|
||||
|
||||
final class SerializerContextFactory
|
||||
{
|
||||
private $factory;
|
||||
private $reader;
|
||||
|
||||
public function __construct(AdvancedMetadataFactoryInterface $factory, Reader $reader)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
$this->reader = $reader;
|
||||
}
|
||||
|
||||
public function create($subject, array $groups)
|
||||
{
|
||||
return SerializationContext::create()->setGroups($this->groups($subject, $groups));
|
||||
}
|
||||
|
||||
private function groups($subject, array $groups)
|
||||
{
|
||||
$metadata = $this->factory->getMetadataForClass(is_object($subject) ? get_class($subject) : $subject);
|
||||
$properties = $metadata instanceof ClassHierarchyMetadata
|
||||
? collect($metadata->classMetadata)->flatMap(property('propertyMetadata'))
|
||||
: $metadata->propertyMetadata;
|
||||
|
||||
$fields = [];
|
||||
/** @var PropertyMetadata $property */
|
||||
foreach ($properties as $property) {
|
||||
try {
|
||||
$annotation = $this->getAnnotationForProperty($property);
|
||||
if ($annotation && !empty($fieldGroups = $this->map($annotation, $groups))) {
|
||||
$type = $property->type;
|
||||
$class = $type['name'] !== 'array' ? $type['name'] : $type['params'][0];
|
||||
|
||||
$fields[$property->name] = $this->groups($class, $fieldGroups);
|
||||
}
|
||||
} catch (\ReflectionException $e) { }
|
||||
}
|
||||
|
||||
return array_merge($groups, $fields);
|
||||
}
|
||||
|
||||
private function getAnnotationForProperty(PropertyMetadata $metadata)
|
||||
{
|
||||
$reflection = new \ReflectionClass($metadata->class);
|
||||
|
||||
try {
|
||||
$property = $reflection->getProperty($metadata->name);
|
||||
/** @var SerializeAs $annotation */
|
||||
return $this->reader->getPropertyAnnotation($property, SerializeAs::class);
|
||||
} catch (\ReflectionException $exception) {
|
||||
$method = $reflection->getMethod($metadata->getter);
|
||||
return $this->reader->getMethodAnnotation($method, SerializeAs::class);
|
||||
}
|
||||
}
|
||||
|
||||
private function map(SerializeAs $annotation, array $groups)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($groups as $group) {
|
||||
if (array_key_exists($group, $annotation->map)) {
|
||||
$result[] = $annotation->map[$group];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user