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 - 将 json 反序列化为实体数组

Symfony SerializerInterface 将 json 反序列化为类不起作用

将 Json 反序列化为实体框架无法将 int 转换为类型

在 symfony JMS PHP 中将单个字符串属性反序列化为对象

Symfony2 将实体对象序列化为会话

将 JSON 包反序列化为具有自定义属性名称的类