如何在Symfony Serializer中反序列化对象数组?

时间:2017-11-13 20:58:28

标签: php symfony serializer

是否可以在Symfony Serializer中反序列化属性中的对象数组?我有一个Boss类,其$Npc = []属性需要包含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
    }]
}

4 个答案:

答案 0 :(得分:6)

我找到了办法:)我通过Composer安装了Symfony PropertyAccess包。使用此包,您可以添加加法器,删除器和缓冲器。这样,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起,您还必须创建一个移除方法。否则它就行不通(没有错误或警告)。

答案 1 :(得分:1)

我在这个很长时间内一直在努力,却没有得到结果。 每次我添加一个加法器函数时,objectnormalizer想要调用这个函数,但得到的错误类似于“字段xyz应该是xyz []类型,给定的数组”。

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

希望这对某人有用。

答案 2 :(得分:0)

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

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

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

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

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

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 获取现有值并允许比较。另外两个需要存在,以便通过添加缺失的和删除不再存在的实体来调整现有值以匹配预期值。

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

答案 3 :(得分:-1)

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

node .\a.js
err: null
 stdout: B was called

 stderr:

您可以在handling arrays

的文档中找到有关此内容的更多信息