Огромное спасибо
BoShurik за комментарий о пакете
symfony/property-info
Решение проблемы несериализуемых вложенных элементов внутри объекта:
Установить все пакеты
symfony/serializer
symfony/property-access
symfony/property-info
phpdocumentor/reflection-docblock
Внутри класса, где есть свойство - массив объектов, прописать аннотацию
<?php
namespace App\Pagination;
use App\Entity\NearEarthObject;
class PaginatedCollection
{
/**
* @param NearEarthObject[] $items
*/
private $items;
...
Внутри метода, где происходит сериализация, прописать:
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$converter = new CamelCaseToSnakeCaseNameConverter();
$normalizers = [
new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
new ArrayDenormalizer(),
new ObjectNormalizer(null, $converter, null, $extractor),
];
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');
Итоговый контроллер<?php
namespace App\Controller;
use App\Entity\NearEarthObject;
use App\Pagination\PaginationFactory;
use App\Repository\NearEarthObjectRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
class NearEarthObjectController extends AbstractController
{
private EntityManagerInterface $entityManager;
/**
* @var PaginationFactory
*/
private $paginationFactory;
public function __construct(EntityManagerInterface $entityManager, PaginationFactory $paginationFactory)
{
$this->entityManager = $entityManager;
$this->paginationFactory = $paginationFactory;
}
/**
* @Route("/neo/hazardous", name="neo_hazardous", methods={"GET"})
*/
public function hazardousAction(Request $request, ObjectNormalizer $objectNormalizer)
{
/**
* @var NearEarthObjectRepository $nearEarthObjectRepository
*/
$nearEarthObjectRepository = $this
->entityManager
->getRepository(NearEarthObject::class);
//TODO: add getting is_hazardous=1
$queryBuilder = $nearEarthObjectRepository->findAllQueryBuilder();
$paginatedCollection = $this
->paginationFactory
->createCollection($queryBuilder, $request, 'neo_hazardous');
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$converter = new CamelCaseToSnakeCaseNameConverter();
$normalizers = [
new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
new ArrayDenormalizer(),
new ObjectNormalizer(null, $converter, null, $extractor),
];
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');
return new Response($serializedPaginatedCollection, 200, [
'Content-Type' => 'application/json',
]);
}
}
Источники:
Issue на github, который показывает решение
The Symfony Serializer: a great, but complex component
UPD. Еще раз спасибо
BoShurik за уточнения - если изначально поставить
symfony/serializer-pack
, то все пакеты будут установлены сразу, аннотация
@param NearEarthObject[] $items
не нужна, а кусок
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$converter = new CamelCaseToSnakeCaseNameConverter();
$normalizers = [
new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d']),
new ArrayDenormalizer(),
new ObjectNormalizer(null, $converter, null, $extractor),
];
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
$serializedPaginatedCollection = $serializer->serialize($paginatedCollection, 'json');
return new Response($serializedPaginatedCollection, 200, [
'Content-Type' => 'application/json',
]);
сводится к
return $this->json($paginatedCollection);
и сериалайзер выполняет всю работу автоматически