Symfony - 将 json 反序列化为实体数组
Posted
技术标签:
【中文标题】Symfony - 将 json 反序列化为实体数组【英文标题】:Symfony - Deserialize json to an array of entities 【发布时间】:2014-05-27 21:48:53 【问题描述】:我有一个通过 get API 调用收到的 json 对象。我进行此调用以接收对象列表。这是一个帖子列表......所以我有一个帖子对象数组。
这里是输出:
"total":2,
"data":[
"id":2,
"user":
"id":1,
"username":"sandro.tchikovani"
,
"description":"cool",
"nb_comments":0,
"nb_likes":0,
"date_creation":"2014-04-13T20:07:34-0700"
,
"id":1,
"user":
"id":1,
"username":"sandro.tchikovani",
,
"description":"Premier pooooste #lol",
"nb_comments":0,
"nb_likes":0,
"date_creation":"2014-04-13T15:15:35-0700"
]
我想反序列化数据部分... 问题是 Symfony 中的序列化器给了我一个错误...
我遇到的错误:
Class array<Moodress\Bundle\PosteBundle\Entity\Poste> does not exist
我如何反序列化:
$lastPosts = $serializer->deserialize($data['data'], 'array<Moodress\Bundle\PosteBundle\Entity\Poste>', 'json');
如何反序列化数据数组...拥有一个帖子数组。我想给我的观点 .twig 一个数组 Poste...我在反序列化时确实精确了类型...所以我找不到问题所在...
谢谢。
【问题讨论】:
您的解决方案有什么进展吗?我想知道如何让 JMS 匹配 json 中这样的data
对象。
我别无选择...我只是在数组上为每个值创建了一个,并反序列化每个值的数据...我本来希望以另一种方式使用它,但我不能找不到任何其他解决方案。
【参考方案1】:
我认为这里最好的解决方案是创建新的 PosteResponse 类,比如这个:
namespace Moodress\Bundle\PosteBundle\Response;
use JMS\Serializer\Annotation\Type;
class PosteResponse
/**
* @Type("integer")
*/
private $total;
/**
* @Type("array<Moodress\Bundle\PosteBundle\Entity\Poste>")
*/
private $data;
//getters here
并反序列化您对该类的响应:
$response = $serializer->deserialize(
$json,
'Moodress\Bundle\PosteBundle\Response\PosteResponse',
'json'
);
$posts = $response->getData();
这样就可以了,而且它不需要您手动解码和编码您的 json,这在我看来是荒谬的。
【讨论】:
【参考方案2】:自从Symfony Serializer Component 2.8
反序列化对象数组:
$persons = $serializer->deserialize($data, 'Acme\Person[]', 'json');
https://symfony.com/doc/master/components/serializer.html#handling-arrays
【讨论】:
【参考方案3】:我发现一个不太理想的解决方案是首先在表示数据数组的节点处对 json 数据进行解码然后再次编码。例如在你的情况下:
$json = json_decode($json);
$json = json_encode($json->data);
$serializer->deserialize($json, 'array<Moodress\Bundle\PosteBundle\Entity\Poste>', 'json');
肯定有比这更好的解决方案,但这似乎比上述反序列化 json 的解决方案更优雅。
【讨论】:
正是我需要的。这应该是公认的答案。【参考方案4】:错误很明显。您的字符串与任何现有类都不匹配。
The example in official documentation says:
$person = $serializer->deserialize($data,'Acme\Person','xml');
在你的情况下,它应该更像:
$person = $serializer->deserialize($data['data'],'Moodress\Bundle\PosteBundle\Entity\Poste','json');
更新:
那好吧。
首先,您的 json 文件似乎无效(使用http://jsonlint.com/ 对其进行测试)。小心那个。
其次,您必须将您的 json 作为数组获取
$data = json_decode($yourJsonFile, true);
然后您可以使用
访问每个“数据”数组foreach($data['data'] as $result)
/* Here you can hydrate your object manually like:
$person = new Person();
$person->setId($user['id']);
$person->setDescription($user['description']);
Or you can use a denormalizer. */
【讨论】:
问题是 $data['data'] 是一个 Postes 数组......不仅仅是一个......所以我必须让序列化程序了解我想反序列化我的数组实体类型。你知道我的意思吗? 是的,我想过......正如你所说,它可以解决问题,但在文档中它说可以直接序列化数组......如果我没有找到其他解决方案,我会像您演示的那样逐步完成。我只是觉得使用数组类型会更好......但我不知道为什么,JMSSerialize 不喜欢我的代码。【参考方案5】:我会做这样的事情
class PostsModel
/**
* @var int
*/
private $total;
/**
* @var PostModel[]
*/
private $data;
class PostModel
/**
* @var int
*/
private $id;
/**
* @var UserModel
*/
private $user;
/**
* @var string
*/
private $description;
/**
* @var int
*/
private $nb_comments;
/**
* @var int
*/
private $nb_likes;
/**
* @var \DateTime
*/
private $date_creation;
class UserModel
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $username;
在控制器中
$posts = $this->serializer->deserialize($data, PostsModel::class, 'json');
这将返回带有 $data 属性的 $postsModel,其中包含您的实体数组
【讨论】:
【参考方案6】:如果有人正在搜索如何使用 Symfony Serializer 解码对象数组:
use Moodress\Bundle\PosteBundle\Entity\Poste;
// your json data
$data = '
"total":2,
"data":[
...,
...
]
';
$lastPosts = $serializer->deserialize(
$data['data'],
'Poste[]', // or Poste::class.'[]',
'json'
);
注意你需要在你的类名后面加上[]
,这样Symfony就会把你的json数据识别为一个对象数组。
【讨论】:
以上是关于Symfony - 将 json 反序列化为实体数组的主要内容,如果未能解决你的问题,请参考以下文章
Symfony SerializerInterface 将 json 反序列化为类不起作用