Thanks to visit codestin.com
Credit goes to github.com

Skip to content

nested XML attributes not deserializing #51827

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

Closed
tacman opened this issue Oct 3, 2023 · 4 comments
Closed

nested XML attributes not deserializing #51827

tacman opened this issue Oct 3, 2023 · 4 comments

Comments

@tacman
Copy link
Contributor

tacman commented Oct 3, 2023

Symfony version(s) affected

all

Description

When serializing an entity with related entities, and those entities are configured to have attributes, deserializing does not work.

<?xml version="1.0"?>
<product description="Wool sweater">
  <property name="color">blue</property>
  <property name="size">small</property>
</product>

This XML can be generated from the entity but not deserialized.

How to reproduce

$product = (new Product())
    ->setDescription("Wool sweater");
$product
    ->addProperty((new Property())->setName('color')->setValue('blue'))
    ->addProperty((new Property())->setName('size')->setValue('small'))
    ;

$context = [
    'xml_root_node_name' => 'product',
    'groups' => ['xml'],
    'xml_standalone' => false,
    'xml_format_output' => true,
];
$xml = $this->serializer->serialize($product, 'xml', $context);

This works as expected, the $xml string is now:

<?xml version="1.0"?>
<product description="Wool sweater">
  <property name="color">blue</property>
  <property name="size">small</property>
</product>

But deserializing that XML doesn't work:

        /** @var Product $product2 */
        $product2 = $this->serializer->deserialize($xml, Product::class, 'xml');

        dump($product2); // nothing is set :-(

The Serializer is configured so that Product description and Property name are attributes.

# config/serialization.yaml
App\Entity\Product:
  attributes:
    description:
      serialized_name: '@description'
      groups: ['xml']
    properties:
      serialized_name: 'property'
      groups: ['xml']

App\Entity\Property:
  attributes:
    name:
      serialized_name: '@name'
      groups: ['xml']
    value:
      serialized_name: '#'
      groups: ['xml']

The entities are simple and were created with bin/console make:entity. Setters and getters are generated and so not shown.

#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private $id;

    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private $description;

    #[ORM\OneToMany(mappedBy: 'product', targetEntity: Property::class, orphanRemoval: true)]
    private $properties;

    public function __construct()
    {
        $this->properties = new ArrayCollection();
    }
#[ORM\Entity(repositoryClass: PropertyRepository::class)]
class Property
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private $id;

    #[ORM\Column(type: 'string', length: 255)]
    private $name;

    #[ORM\Column(type: 'string', length: 255)]
    private $value;

    #[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'properties')]
    #[ORM\JoinColumn(nullable: false)]
    private $product;

Possible Solution

I'm guessing that the issue is that the serialization.yaml file isn't configured correctly, but since serializing works, I'm not sure what the error is.

Additional Context

I thought this might be related to #51594 or #51701, but the issue persists.

@tacman
Copy link
Contributor Author

tacman commented Oct 3, 2023

I created a small project that shows this problem:

git clone [email protected]:tacman/xml-serializer-bug-demo.git && cd xml-serializer-bug-demo && composer install && bin/console app:bug

bin/console server:start
# the home page dumps some things, in case the serializer profile provides some clues.

@squrious
Copy link
Contributor

Hi there! Thank you for reporting the issue. I tried some config on the reproducer (thank you @tacman), and in fact, passing the groups options in the context for deserialization will deserialize the properties as expected:

$product = (new Product())
    ->setDescription("Wool sweater")
    ->addProperty((new Property())->setName('color')->setValue('blue'))
    ->addProperty((new Property())->setName('size')->setValue('small'))
;
$context = [
    'xml_root_node_name' => 'product',
    'groups' => ['xml'],
    'xml_standalone' => false,
    'xml_format_output' => true,
];
$xml = $this->serializer->serialize($product, 'xml', $context);
$context = [
    'xml_root_node_name' => 'product',
    'groups' => ['xml']
];
$product2 = $this->serializer->deserialize($xml, Product::class, 'xml', $context);

dump($product2):

image

@mtarld
Copy link
Contributor

mtarld commented Oct 25, 2023

Indeed, you need to have a matching group here.

According to the serialization.yaml file, properties belongs to the xml group. Therefore, if the group doesn't match, they'll be ignored.

So you can either provide the xml or the * group in the context to make it work.

@tacman
Copy link
Contributor Author

tacman commented Oct 25, 2023

Oh, now it makes sense! Deserializing needs a $context too, with the group.

Thanks very much for solving this!

@tacman tacman closed this as completed Oct 25, 2023
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

5 participants