2017-09-12 2 views
0

J'ai un problème en essayant de sérialiser un tableau d'entité Jeu en JSON. J'ai au début une exception de référence circulaire que j'ai réussi à corriger (mais peut-être que ma solution est la source du problème).Symfony2 FOSRESTBundle groupe d'entités de sérialisation à JSON

Actuellement, ma requête/mes jeux renvoient un tableau JSON valide mais n'est pas correctement affiché dans le navigateur et l'application ne parvient pas à l'analyser. Chrome me retourner l'erreur suivante:

ressources interprété comme document mais transféré avec l'application type MIME /JSON

Ce qui est surprenant est que je n'envoie le type de contenu application/JSON. Les mêmes en-têtes sont utilisés avec une autre demande/joueurs et sont correctement affichés et analysés sans erreur.

J'ai une relation bidirectionnelle entre ces deux entité: jeu & joueur.

jeu Entité:

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Game 
* 
* @ORM\Table(name="game") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository") 
*/ 
class Game 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\TournamentType", inversedBy="games") 
    */ 
    private $refType; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="TournamentDate", type="date") 
    */ 
    private $tournamentDate; 

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ground", inversedBy="games") 
    */ 
    private $ground; 

    /** 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Referee", inversedBy="games") 
    */ 
    private $referee; 

    /** 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Player", cascade={"persist"}) 
    */ 
    private $players; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="NbSetsPlayerOne", type="integer") 
    */ 
    private $nbSetsPlayerOne; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="NbSetsPlayerTwo", type="integer") 
    */ 
    private $nbSetsPlayerTwo; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="IsOver", type="boolean") 
    */ 
    private $isOver; 

    public function __construct(){ 
     $this->players = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

joueur Entité:

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Player 
* 
* @ORM\Table(name="player") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\PlayerRepository") 
*/ 
class Player 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="LastName", type="string", length=255) 
    */ 
    private $lastName; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="FirstName", type="string", length=255) 
    */ 
    private $firstName; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="Sexe", type="string", length=255) 
    */ 
    private $sexe; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="Country", type="string", length=255) 
    */ 
    private $country; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="Ranking", type="integer") 
    */ 
    private $ranking; 

    /** 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Game", cascade={"persist"}) 
    */ 
    private $games; 


    public function __construct(){ 
     $this->games = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

App/Config/config.yml:

# FOSRestBundle API Configuration 
fos_rest: 
    format_listener: 
     rules: 
      - { path: '^/game', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/ground', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/player', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/referee', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/tournament-type', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/user', priorities: 'json', fallback_format: json, prefer_extension: true } 
      - { path: '^/', priorities: 'json', fallback_format: json, prefer_extension: true } 

Gamecontroller:

/** 
* getGamesAction 
* 
* @Get("/games") 
* 
* @param Request $request 
* @return type 
*/ 
public function getGamesAction(Request $request) {   
    $games = $this->getDoctrine()->getManager()->getRepository("AppBundle:Game")->findAll();  
    if (count($games) === 0) { 
     $view = $this->view("No Game found.", 404); 
     return $this->handleView(); 
    } 

    $encoder = new JsonEncoder(); 
    $normalizer = new ObjectNormalizer(); 
    $normalizer->setIgnoredAttributes(array('games', 'players')); 
    $normalizer->setCircularReferenceHandler(function ($object) { 
     return $object->getId(); 
    }); 
    $serializer = new Serializer(array($normalizer), array($encoder)); 
    $data = $serializer->serialize($games, 'json'); 
    $view = $this->view($data) 
       ->setTemplateVar('games') 
       ->setTemplate($this->template); 
    //    ->setHeader('Content-Type', 'application/json; charset=UTF-8'); 
    return $this->handleView($view); 
} 

Voici les en-têtes utilisés pour obtenir /jeux:

Cache-Control: no-cache 
Connection: close 
Content-Type: application/json 
Date: Tue, 12 Sep 2017 12:35:45 +0200, Tue, 12 Sep 2017 10:35:45 GMT 
Host: localhost:8000 
X-Debug-Token: d072dd 
X-Debug-Token-Link: http://localhost:8000/app_dev.php/_profiler/d072dd 
X-Powered-By: PHP/7.1.1 

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Encoding: gzip, deflate 
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3 
Cache-Control: max-age=0 
Connection: keep-alive 
Cookie: cookieconsent_dismissed=yes; _ga=GA1.1.372052120.1482146348; PHPSESSID=l1fgb45492lr02a6hi10rat7ha 
Host: localhost:8000 
Upgrade-Insecure-Requests: 1 
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0 

Et ceux pour obtenir /joueurs:

Cache-Control: no-cache 
Connection: close 
Content-Type: application/json 
Date: Tue, 12 Sep 2017 12:38:18 +0200, Tue, 12 Sep 2017 10:38:18 GMT 
Host: localhost:8000 
X-Debug-Token: 609af7 
X-Debug-Token-Link: http://localhost:8000/app_dev.php/_profiler/609af7 
X-Powered-By: PHP/7.1.1 

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Encoding: gzip, deflate 
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3 
Connection: keep-alive 
Cookie: cookieconsent_dismissed=yes; _ga=GA1.1.372052120.1482146348; PHPSESSID=l1fgb45492lr02a6hi10rat7ha 
Host: localhost:8000 
Upgrade-Insecure-Requests: 1 
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0 

Vous pouvez accéder à un exemple de /jeux rendu vue JSON : JSON shared URL

Répondre

0

Le type de contenu application/json n'est pas t corrigé, donc je parviens à contourner dans le countroller en corrigeant manuellement le codage UTF-8 (qui est le codage par défaut de l'application/json) et la chaîne renvoyée à un objet JSON.

Encoding:

$encoder = new JsonEncoder(new JsonEncode(JSON_UNESCAPED_UNICODE), new JsonDecode(false)); 

chaîne Convertir en objet JSON:

$this->view(json_decode($data, true)) 

Ma méthode de commande est maintenant:

/** 
* getGamesAction 
* 
* @Get("/games") 
* 
* @param Request $request 
* @return type 
*/ 
public function getGamesAction(Request $request) {   
    $games = $this->getDoctrine()->getManager()->getRepository("AppBundle:Game")->findAll();  
    if (count($games) === 0) { 
     $view = $this->view("No Game found.", 404); 
     return $this->handleView(); 
    } 

    $encoder = new JsonEncoder(new JsonEncode(JSON_UNESCAPED_UNICODE), new JsonDecode(false)); 
    $normalizer = new ObjectNormalizer(); 
    $normalizer->setIgnoredAttributes(array('games', 'players')); 
    $normalizer->setCircularReferenceHandler(function ($object) { 
     return $object->getId(); 
    }); 
    $serializer = new Serializer(array($normalizer), array($encoder)); 
    $data = $serializer->serialize($games, 'json'); 
    $view = $this->view(json_decode($data, true)) 
       ->setTemplateVar('games') 
       ->setTemplate($this->template) 
       ->setHeader('Content-Type', 'application/json; charset=UTF-8') 
       ->setFormat('json'); 
    return $this->handleView($view); 
}