【问题标题】:Symfony - Deserialize json to an array of entitiesSymfony - 将 json 反序列化为实体数组
【发布时间】: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 对象。
  • 我别无选择...我只是在数组上为每个值创建了一个,并反序列化每个值的数据...我本来希望以另一种方式使用它,但我不能找不到任何其他解决方案。

标签: php json symfony deserialization jmsserializerbundle


【解决方案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数据识别为一个对象数组。

        【讨论】:

          猜你喜欢
          • 2021-09-27
          • 1970-01-01
          • 2018-09-19
          • 1970-01-01
          • 1970-01-01
          • 2016-12-21
          • 1970-01-01
          • 2016-10-11
          • 1970-01-01
          相关资源
          最近更新 更多