Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Denormalization of a Collection of Objets as a Constructor Argument #28475

Closed
alsciende opened this issue Sep 15, 2018 · 3 comments
Closed

Comments

@alsciende
Copy link
Contributor

Description
The documentation for ObjectNormalizer states that "It supports calling the constructor during the denormalization process." but that is not true when one of the constructor arguments is an array of objects. Currently (since #19649), is is only possible to denormalize an "array of objects" property if that property has a setter method or is public.

Example

#!/usr/bin/env php
<?php

namespace App;

use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

require __DIR__ . '/vendor/autoload.php';

class Item
{
    /**
     * @var string
     */
    private $id;

    /**
     * Item constructor.
     * @param string $id
     */
    public function __construct(string $id)
    {
        $this->id = $id;
    }

    public function getId(): string
    {
        return $this->id;
    }
}

class Pack
{
    /**
     * @var Item[]
     */
    private $items;

    /**
     * Pack constructor.
     * @param Item[] $items
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }

    public function getItems(): array
    {
        return $this->items;
    }
}

$phpDocExtractor = new PhpDocExtractor();
$normalizer = new ObjectNormalizer(null, null, null, $phpDocExtractor);
$serializer = new Serializer([$normalizer, new ArrayDenormalizer()]);

$itemData = ["id" => "1"];
$listData = ['items' => [$itemData]];

dump($serializer->denormalize($listData, Pack::class));

Executing this script from a project root will print:

App\Pack {#20
  -items: array:1 [
    0 => array:1 [
      "id" => "1"
    ]
  ]
}

The expected result is:

App\Pack {#18
  -items: array:1 [
    0 => App\Item {#40
      -id: "1"
    }
  ]
}

That expected result can be obtained by replacing the constructor of Pack with a setter for $items:

#!/usr/bin/env php
<?php

namespace App;

use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

require __DIR__ . '/vendor/autoload.php';

class Item
{
    /**
     * @var string
     */
    private $id;

    /**
     * Item constructor.
     * @param string $id
     */
    public function __construct(string $id)
    {
        $this->id = $id;
    }

    public function getId(): string
    {
        return $this->id;
    }
}

class Pack
{
    /**
     * @var Item[]
     */
    private $items;

    public function setItems(array $items): self
    {
        $this->items = $items;

        return $this;
    }

    public function getItems(): array
    {
        return $this->items;
    }
}

$phpDocExtractor = new PhpDocExtractor();
$normalizer = new ObjectNormalizer(null, null, null, $phpDocExtractor);
$serializer = new Serializer([$normalizer, new ArrayDenormalizer()]);

$itemData = ["id" => "1"];
$listData = ['items' => [$itemData]];

dump($serializer->denormalize($listData, Pack::class));
@jsamouh
Copy link
Contributor

jsamouh commented Sep 27, 2018

you're right @alsciende
the method instantiateObject never use propertyTypeExtractor

@dunglas WDYT ?

@jsamouh
Copy link
Contributor

jsamouh commented Sep 28, 2018

got it
#27221
duplicate #25524
cc @xabbuh

@joelwurtz
Copy link
Contributor

This should have been fixed in #29513

@xabbuh xabbuh closed this as completed Mar 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants