Décrivez ici votre problème ou ce que vous cherchez à faire.

<?php

namespace App\Serializer\Normalizer;

use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

class CourseNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
{
    public function __construct(private ObjectNormalizer $normalizer)
    {
    }

    public function normalize($object, string $format = null, array $context = []): array
    {
        $data = $this->normalizer->normalize($object, $format, $context);

        // TODO: add, edit, or delete some data

        return $data;
    }

    public function supportsNormalization($data, string $format = null, array $context = []): bool
    {
        return $data instanceof \App\Entity\Course;
    }

    public function hasCacheableSupportsMethod(): bool
    {
        return true;
    }
}

Ce que je veux

Je veux serializer mes données en JSON

Décrivez ce que vous cherchez à obtenir.

Ce que j'obtiens
App\Serializer\Normalizer\CourseNormalizer::__construct(): Argument #1 ($normalizer) must be of type Symfony\Component\Serializer\Normalizer\ObjectNormalizer, Symfony\Component\Serializer\Debug\TraceableNormalizer given, called in H:\Php\Framework\Symfony\Evaluation\var\cache\dev\ContainerYNqPeoi\getDebug_SerializerService.php on line 85
Décrivez vos éventuelles erreurs ou ce que vous obtenez à la place de ce que vous attendez :(

11 réponses


gillesr
Réponse acceptée

Oui, tu peux soit préciser le max depth, soit utiliser les groupes pour choisir les champs à sérialiser dans tes entités, l'avantage de cette solution,c'est que tu peux définir les champs que tu vas récupérer sur les entités liées en fonction de ton contexte, l'inconvénient étant que c'est un peu plus verbeux (il faut ajouter les annotations dans les entités).
Par ex :


    #[Groups(['course:read'])]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    #[Groups(['course:read', 'professor:read'])]
    private ?string $name = null;

    #[ORM\Column(length: 20, nullable: true)]
    #[Groups(['course:read'])]
    private ?string $alias = null;

    #[ORM\Column(type: Types::DATETIME_MUTABLE)]
    #[Groups(['course:read'])]
    private ?\DateTimeInterface $create_at = null;

et dans le controleur :


   return $this->json($course->search($request->query->get('q')), 200, [], ['groups' => ['course:read']]);

De cette façon tu peux afficher les champs que tu souhaites en fonction du groupe appelé.

Il nous faut le code qui utilise ton normalizer pour mieux comprendre.
En tout cas l'erreur est claire : tu passes un objet de type TraceableNormalizer alors que le constructeur s'attend à un ObjectNormalizer.

labeya_
Auteur
<?php

namespace App\Controller;

use App\Repository\CourseRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
 * Summary of ApiController
 */
class ApiController extends AbstractController
{

    /**
     * @param Request $request
     * @param CourseRepository $course
     * @return \Symfony\Component\HttpFoundation\JsonResponse
     */
    #[Route('/api/search/course', 'api.course.search')]
    public function courseSearch(Request $request, CourseRepository $course)
    {
        return $this->json($course->search($request->query->get('q')));
    }
}
labeya_
Auteur

je comprends pas pourquoi y a cette erreur.

labeya_
Auteur

quand j'essaie de récupèrer les données en json sans la serialization
j'ai une erreur

A circular reference has been detected when serializing the object of class "App\Entity\Course" (configured limit: 1).

App\Entity\Course ressemble à quoi ?

Et tu n'as pas fait voir le code qui utilise le normalizer. C'est dans $course->search() ?

Bonjour,

Il faudrait voir les groupes de sérialisation que tu définis dans tes entités (et entités liées).
Sans voir, je dirais que tu sérialises une relation sur une entité liée et que dans l'entité liée tu fais la même chose vers l'entité Course.

labeya_
Auteur
<?php

namespace App\Entity;

use App\Repository\CourseRepository;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: CourseRepository::class)]
class Course
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    #[ORM\Column(length: 20, nullable: true)]
    private ?string $alias = null;

    #[ORM\Column]
    private ?int $pond = null;

    #[ORM\Column(type: Types::DATETIME_MUTABLE)]
    private ?\DateTimeInterface $create_at = null;

    #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
    private ?\DateTimeInterface $update_at = null;

    #[ORM\ManyToOne(inversedBy: 'courses', cascade:['persist'])]
    #[ORM\JoinColumn(nullable: false)]
    private ?Professor $professor = null;

    #[ORM\ManyToOne(inversedBy: 'courses')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Level $level = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $description = null;

    public function __construct()
    {

        if (is_null($this->create_at)) {
            $this->create_at = new DateTime();
        }
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getAlias(): ?string
    {
        return $this->alias;
    }

    public function setAlias(?string $alias): self
    {
        $this->alias = $alias;

        return $this;
    }

    public function getPond(): ?int
    {
        return $this->pond;
    }

    public function setPond(int $pond): self
    {
        $this->pond = $pond;

        return $this;
    }

    public function getCreateAt(): ?\DateTimeInterface
    {
        return $this->create_at;
    }

    public function setCreateAt(\DateTimeInterface $create_at): self
    {
        $this->create_at = $create_at;

        return $this;
    }

    public function getUpdateAt(): ?\DateTimeInterface
    {
        return $this->update_at;
    }

    public function setUpdateAt(?\DateTimeInterface $update_at): self
    {
        $this->update_at = $update_at;

        return $this;
    }

    public function getProfessor(): ?Professor
    {
        return $this->professor;
    }

    public function setProfessor(?Professor $professor): self
    {
        $this->professor = $professor;

        return $this;
    }

    public function __toString()
    {
        return $this->getName() . ' ' . $this->getLevel();
    }

    public function getLevel(): ?Level
    {
        return $this->level;
    }

    public function setLevel(?Level $level): self
    {
        $this->level = $level;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $descroption): self
    {
        $this->description = $descroption;

        return $this;
    }
}

à ça

Course -> professor -> courses -> Professor

etc

J'ai eu le même problème la semaine dernière et j'ai ajouté

     * @MaxDepth(1)

sur les relations et hop.

labeya_
Auteur

ça marche toujours pas

labeya_
Auteur

il fallait installer

composer require symfony/serializer

https://www.novaway.fr/blog/tech/comment-utiliser-le-serializer-symfony