JMS反序列化Object中的ArrayCollection

时间:2015-05-21 14:53:10

标签: php serialization doctrine-orm jms-serializer

我试图在我的应用程序(而不是Symfony)中使用JMS序列化程序,并希望将JSON对象反序列化为Doctrine Entity。
普通属性正在反序列化,但我无法使ArrayCollections工作。

这是我的产品JSON的摘录:

{
  "id": 2,
  "name": "Shirt blue",
  "attributeValues": [
    {
      "id": 4,
      "title": "S",
      "attributeId": 2
    },
    {
      "id": 7,
      "title": "Eterna",
      "attributeId": 3
    }
  ]
}

这是我的产品实体:

<?php

namespace Vendor\App\Common\Entities;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="product")
 * @JMS\ExclusionPolicy("all")
 */
class Product extends AbstractEntity {

    /**
     * @var int $id
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @JMS\Groups({"search"})
     * @JMS\Expose
     * @JMS\Type("integer")
     */
    protected $id;

    /**
     * @var string $name
     * @ORM\Column(name="name", type="string", nullable=false)
     * @JMS\Expose
     * @JMS\Groups({"search"})
     * @JMS\Type("string")
     */
    protected $name;

    /**
     * @var ArrayCollection $attributeValues
     * @ORM\ManyToMany(targetEntity="Vendor\App\Common\Entities\Attribute\Value")
     * @ORM\JoinTable(name="products_values",
    *      joinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="id")},
    *      inverseJoinColumns={@ORM\JoinColumn(name="value_id", referencedColumnName="id")}
     *      )
     * @JMS\Expose
     * @JMS\MaxDepth(2)
     * @JMS\Groups({"search"})
     * @JMS\Type("ArrayCollection<Vendor\App\Common\Entities\Attribute\Value>")
     */
    protected $attributeValues;

    public function __construct() {
        $this->attributeValues = new ArrayCollection();
    }

    /**
     * @return ArrayCollection
     */
    public function getAttributeValues() {
        return $this->attributeValues;
    }

    /**
     * @param ArrayCollection $attributeValues
     */
    public function setAttributeValues($attributeValues) {
        $this->attributeValues = $attributeValues;
    }

    /**
     * @param Value $attributeValue
     */
    public function addAttributeValue($attributeValue) {
        $this->attributeValues->add($attributeValue);
    }

    /**
     * @param Value $attributeValue
     */
    public function removeAttributeValue($attributeValue) {
        $this->attributeValues->removeElement($attributeValue);
    }

}

这是我应该在ArrayCollection中反序列化的Value实体:

<?php

namespace Vendor\App\Common\Entities\Attribute;

use Vendor\App\Common\Entities\AbstractEntity,
    Doctrine\ORM\Mapping as ORM,
    JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Entity
 * @ORM\Table(name="attribute_value")
 * @JMS\ExclusionPolicy("all")
 */
class Value extends AbstractEntity {

    /**
     * @var int $id
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @JMS\Expose
     * @JMS\Groups({"search"})
     * @JMS\Type("integer")
     */
    protected $id;

    /**
     * @var string $title
     * @ORM\Column(name="title", type="string", nullable=false)
     * @JMS\Expose
     * @JMS\Groups({"search"})
     * @JMS\Type("string")
     */
    protected $title;

    /**
     * @var int $attributeId
     * @ORM\Column(name="attribute_id", type="integer", nullable=false)
     * @JMS\Expose
     * @JMS\Groups({"search"})
     * @JMS\Type("integer")
     */
    protected $attributeId;

    /**
     * OWNING SIDE
     * @var \Vendor\App\Common\Entities\Attribute $attribute
     * @ORM\ManyToOne(targetEntity="Vendor\App\Common\Entities\Attribute", inversedBy="values")
     * @ORM\JoinColumn(name="attribute_id", referencedColumnName="id")
     * @JMS\Expose
     * @JMS\Groups({"search"})
     * @JMS\Type("Vendor\App\Common\Entities\Attribute")
     */
    protected $attribute;

    //Getters and setters ...

}

只是尝试简单地反序列化实体:

$serializer = SerializerBuilder::create()->build();
$entity = $serializer->deserialize($sourceJson, Product::class, 'json');

但是attributeValue ArrayCollection保持为空。我错过了什么?

1 个答案:

答案 0 :(得分:2)

我找到了解决方案。 JMS有一个默认的命名策略,它将camelcase转换为下划线表示法。 默认是命名策略要么寻找注释@SerializedName,如果没有设置,它会将CamelCase转换为下划线。

因此该属性被忽略,因为它与预期的名称不匹配。当然,如果有错误或通知在这里提示搜索问题的位置会更好(比如未知属性会很好)。

$serializer = SerializerBuilder::create()->setPropertyNamingStrategy(new IdenticalPropertyNamingStrategy())->build();

是解决方案。