Bonjour,

A partir d'un controller de mon API, je cherche à renvoyer une liste d'éléments.
Ces éléments sont des objets sérialisés en JSON.

Y'a t-il un moyen natif au Serializer pour faire cela directement plutôt que de construire à la main un JSON qui contient ma liste de plusieurs JSON?

J'éspère me faire comprendre... voici mon code.

"```"

[Route('/product/list/custom', name: 'product_list')]
public function productsList(ProductRepository $rep, SerializerService $serializerService):Response
{
    $pdt_liste = $rep->findAll();
    $datas = "{";
    $i = 1;
    foreach ($pdt_liste as $pdt)
    {
        $serializer = $serializerService->getSerializer();
        $pdtJson = $serializer->serialize(
            $pdt,
            'json',
            [
                AbstractNormalizer::IGNORED_ATTRIBUTES => ['products','prices']
            ]
         );
         $datas .= '"'.$i.'": '.$pdtJson.",";
         $i++;
     }
    $datas = substr($datas,0,-1);
    $datas .= "}";
    return new Response($datas)  ;
}
"```"

Je précise que j'ai utilisé un Serializer car dans ma liste de 'pdt' il y a une relation avec une table 'marque' et que sans ça je n'ai pas l'objet 'marque' hydraté complétement , je ne récupèrais que l'ID de 'marque'.

Merci.

6 réponses


Bonjour,
Si ton controleur étend AbstractController (ce qui est le cas par défaut), il y a une méthode json() donc tu peux faire :


return $this->json($pdt_liste);
mick69
Auteur

Merci pour la réponse.

Alors en effet je l'avais utilisée mais comme je le précise à la fin de mon message, avec cette méthode mon objet 'marque' qui est une relation de la table 'product' n'est pas hydraté correctement.
Voici ce que me renvoie la méthode $this->json
"" "marque":"\/api\/marques\/1" ""
Alors que moi j'attends ça:
"" "marque":{"id":1,"marqueNom":"adidas","marqueCode":0 ""

Oui, il faut utiliser les groupes de serialisation en mettant des annotations dans tes entités avec les annotations @Groups.
Il faut mettre l'annotation dans l'objet product et dans l'objet marque sinon le serializer ne prend que l'id des entités liées.

mick69
Auteur

:) je m'y attendais.
J'ai deséspèrement essayer de faire ça hier mais j'avais un pb de référence circulaire.

Je n'ai probablement pas compris où mettre ces annotations.

Si tu as une voie sur laquelle me lancer, je suis preneur.

Dans la class 'PRODUCT' ça serait un truc du genre:

"" [ORM\ManyToOne(targetEntity: Marque::class, inversedBy: 'products')] [ORM\JoinColumn(nullable: false)] [Groups(['testmarque'])] private $marque; ""

Et dans la class 'MARQUE', idem:

"" [ORM\OneToMany(mappedBy: 'marque', targetEntity: Product::class)] [Groups(['testmarque'])] private $products; ""

J'vais tenté de m'y recoller.
Merci

edit: désolé j'ai un souci de mise en forme avec la syntaxe des annotations

La référence circulaire, c'est parceque tu as une liaison qui boucle entre tes deux entités, il faut donc lui préciser un peu les choses.
J'ai fait un petit exemple rapidement :
Voici les champs de la classe Product :


#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['product:read'])]
private $id;

#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $nom;

#[ORM\Column(type: 'float')]
#[Groups(['product:read'])]
private $prix;

#[ORM\ManyToOne(targetEntity: Marque::class, inversedBy: 'products')]
#[ORM\JoinColumn(nullable: false)]
#[Groups(['product:read'])]
private $marque;

Et ceux de la classe Marque :


#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['product:read'])]
private $id;

#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $nom;

#[ORM\Column(type: 'string', length: 255)]
#[Groups(['product:read'])]
private $code;

#[ORM\OneToMany(mappedBy: 'marque', targetEntity: Product::class)]
private $products;

Tu peux voir que j'ai mis le groupe 'product:read' sur les champs que je veux afficher mais pas sur le champ qui fait la relation sinon ça boucle.

Et pour utiliser ça dans le controleur, je précise au serializer quel groupe je demande :

    $products = .... // récupération des products
    return $this->json(
            $products,
            200,
            [],
            ['groups' => 'product:read']
    );
mick69
Auteur

un grand merci à toi.

C'est exactement ce que je cherchais.

Du coup plus d''interêt (pour moi) d'utiliser un Serializer pour l'instant.

Merci