【问题标题】:How can I deserialize an array of objects in Symfony Serializer?如何在 Symfony Serializer 中反序列化对象数组?
【发布时间】:2018-04-26 16:08:06
【问题描述】:

Symfony Serializer 是否可以反序列化属性中的对象数组?我有一个带有$Npc = [] 属性的Boss 类,它需要保存一组Npc 对象。我确实在文档中看到了一些示例,但它们没有说明此功能。我有一个带有 NPC 数组的 json 字符串 例如:

class Boss {

    private $Npc = [];    

    /**
    * @return Npc[]
    */
    public function getNpcs(): array
    {
        return $this->npcs;
    }
}

我正在使用 php7.1 和 symfony/serializer 版本 ^3.3。

编辑: 我已经尝试过 PhpDocExtractor,但它不允许我安装它。 :(

编辑: 这是一个可能的 JSON 值:

{
    "bossname": "Epic boss!",
    "npcs": [{
        "id": 24723,
        "name": "Selin Fireheart",
        "urlSlug": "selin-fireheart",
        "creatureDisplayId": 22642
    }]
}

【问题讨论】:

  • 该死!对不起,我修改了你的问题而不是我的答案。我添加了“使用声明”
  • @db306 哈哈,不过我不是这么想的。看我的回答。

标签: php symfony serialization


【解决方案1】:

以下(完整)示例适用于我使用 Symfony 5.3 组件。它结合了上述一些,并添加了一些更必要的部分:

序列化器需要包含ArrayDenormalizerObjectNormalizerObjectNormalizer 需要正确配置。完整的创作可能如下所示:

return new Serializer(
    [
        new ArrayDenormalizer(),
        new DateTimeNormalizer(),
        new ObjectNormalizer(
            null,
            null,
            null,
            new ReflectionExtractor()
        ),
    ],
    [
        new JsonEncoder(),
    ]
);

似乎顺序对于规范化器/非规范化器很重要,可能是由于优先级。在ObjectNormalizer 之后放置DateTimeNormalizer 将不起作用。

目标类需要提供三个方法以允许映射其他类的数组:

class Place
{
    /**
     * @var OpeningHour[]
     */
    protected $openingHours = [];

    /**
     * @return OpeningHour[]
     */
    public function getOpeningHoursSpecification(): array
    {
        return $this->openingHours;
    }

    public function addOpeningHoursSpecification(OpeningHour $openingHour): void
    {
        $this->openingHours[] = $openingHour;
    }

    public function removeOpeningHoursSpecification(OpeningHour $openingHour): void
    {
    }
}

这三种方法都需要存在。第一个是为了允许 Serializer 获取现有值并允许比较。另外两个需要存在,以便通过添加缺失和删除不再存在的实体来调整现有值以匹配预期值。

以上内容不提供删除的实现,因为这是从单向项目中获取的。

【讨论】:

    【解决方案2】:

    我已经挣扎了这么多小时而没有得到结果。 每次我添加一个加法器函数时,objectnormalizer 都想调用这个函数,但得到一个错误,比如“字段 xyz 应该是 xyz[] 类型,给定数组”。

    这是因为我忘记将ArrayDenormalizer 添加到序列化程序的规范化池中。添加后,一切正常。

    希望这对某人有帮助。

    【讨论】:

    • 什么是“arraynormalizer”?
    • 我找到了,需要ArrayDenormalizer,请申请我的编辑请求。
    【解决方案3】:

    我找到了一种方法来做到这一点:)。我通过 Composer 安装了 Symfony PropertyAccess 包。使用这个包,您可以添加加法器、删除器和 hassers。这样,Symfony Serializer 将自动用正确的对象填充数组。 示例:

    private $npcs = [];
    
    public function addNpc(Npc $npc): void
    {
        $this->npcs[] = $npc;
    }
    
    public function hasNpcs(): bool
    {
        return count($this->npcs) > 0
    }
    

    等等

    这样您就可以将 ObjectNormalizer 用于:

    $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
    

    编辑:至少从 v3.4 开始,您还必须创建一个卸妆方法。否则它将无法正常工作(没有错误或警告)。

    【讨论】:

    • 至少对于 v3.4,您 必须 设置一个卸妆器以使其正常工作(我为此浪费了几个小时的调试时间)。一定要检查你的复数。
    【解决方案4】:

    是的,您可以反序列化数组,但您需要在第二个参数上提供对象以及它实际上是数组的信息。你可以这样做:

    use Symfony\Component\Serializer\Serializer;
    
    class Boss {
    
        private $Npc = [];    
    
        /**
        * @return Npc[]
        */
        public function getNpcs(): array
        {
            return $serializer->deserialize($this->npcs, 'Acme\Npc[]', 'json');
    
        }
    }
    

    您可以在handling arrays 上的文档中找到更多信息

    【讨论】:

    • 将 json 反序列化为对象数组。但我想反序列化为 Npc 属性(参见第一篇文章)。
    • 您的问题是“是否可以在 Symfony 序列化器中反序列化属性中的对象数组?”所以你想要反过来吗?你想要什么:你的对象保存一个对象数组还是一个序列化的 json 代表一个对象数组?
    • 查看我的第二次编辑:我想将那些 npc 对象从 JSON 反序列化为 Boss 类的 npc 属性作为 Npc 类。
    • 它当前反序列化为普通数组。但我想将其反序列化为 Npc 数组
    • 为了成为一个 Npc 数组,你需要一个 Npc 类
    猜你喜欢
    • 2017-08-28
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    相关资源
    最近更新 更多