Symfony2 FOSRESTBundle序列化实体数组到JSON
Symfony2 FOSRESTBundle serialization entity array to JSON
我在尝试序列化 JSON 中的实体数组 Game 时遇到问题。
我一开始就有一个循环引用异常,我设法修复了它(但也许我的解决方案是问题的根源)。
目前我的请求 /games return 一个有效的 JSON 数组,但在浏览器中没有正确显示,应用程序无法解析它。
Chrome return 我出现以下错误:
Resource interpreted as Document but transferred with MIME type
application/json
令人惊讶的是我确实将 Content-Type 发送为 application/json。
完全相同的 headers 用于另一个请求 /players 并且正确显示和解析没有错误。
我在这两个实体之间存在双向关系:游戏和玩家。
实体游戏:
<?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();
}
实体玩家:
<?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 }
游戏控制器:
/**
* 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);
}
这里是 headers 用来获取 /games :
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
那些获得 /玩家 :
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
您可以访问 /games 呈现的 json 视图示例:
JSON shared URL
Application/json 内容类型不正确,所以我设法在计数器中解决手动修复 UTF-8 编码(这是 application/json 的默认编码)和返回的字符串到 JSON 对象。
编码:
$encoder = new JsonEncoder(new JsonEncode(JSON_UNESCAPED_UNICODE), new JsonDecode(false));
转换 JSON 对象中的字符串:
$this->view(json_decode($data, true))
我的控制器方法现在是:
/**
* 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);
}
我在尝试序列化 JSON 中的实体数组 Game 时遇到问题。 我一开始就有一个循环引用异常,我设法修复了它(但也许我的解决方案是问题的根源)。
目前我的请求 /games return 一个有效的 JSON 数组,但在浏览器中没有正确显示,应用程序无法解析它。 Chrome return 我出现以下错误:
Resource interpreted as Document but transferred with MIME type application/json
令人惊讶的是我确实将 Content-Type 发送为 application/json。 完全相同的 headers 用于另一个请求 /players 并且正确显示和解析没有错误。
我在这两个实体之间存在双向关系:游戏和玩家。
实体游戏:
<?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();
}
实体玩家:
<?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 }
游戏控制器:
/**
* 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);
}
这里是 headers 用来获取 /games :
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
那些获得 /玩家 :
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
您可以访问 /games 呈现的 json 视图示例: JSON shared URL
Application/json 内容类型不正确,所以我设法在计数器中解决手动修复 UTF-8 编码(这是 application/json 的默认编码)和返回的字符串到 JSON 对象。
编码:
$encoder = new JsonEncoder(new JsonEncode(JSON_UNESCAPED_UNICODE), new JsonDecode(false));
转换 JSON 对象中的字符串:
$this->view(json_decode($data, true))
我的控制器方法现在是:
/**
* 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);
}