为了让事情变得简单,我有
/*
* @JMS\Discriminator(field = "type", map = {
* "one": "...\ItemOne",
* "two": "...\ItemTwo"
* })
*/
Abstract Class Item {}
.
.
.
class ItemOne extends Item {/* Contains multiple properties */}
class ItemTwo extends Item {/* Contains multiple properties */}
class Example
{
/**
* @var Item[] $items
*
* @ORM\OneToMany(targetEntity="...\Items", mappedBy="holder",cascade={"persist", "remove"})
*/
protected $items;
}
一旦我使用FOSRestBundle序列化这个实体,一切看起来都不错,我得到了项目数组,每个元素都有一个鉴别器字段但是在反序列化时我得到以下错误
"You must define a type for ...\Example::$items."
所以为了解决这个问题我添加了
/**
* @ORM\...
* @JMS\Type("ArrayCollection<...\Item>")
*/
protected $items;
这次序列化的$items
似乎仅限于父类Item
,所有对象都将丢失与子ItemOne
相关的任何属性。 ItemTwo
并且将在没有任何鉴别器字段的情况下进行序列化,因此解除错误将失败并显示错误
"The discriminator field name "type" for base-class "...\Item" was not found in input data."
我该如何解决这个问题?
修改
正如@erlangb所说,这似乎是JMS Serializer
https://github.com/schmittjoh/JMSSerializerBundle/issues/292
虽然我无法使用上述解决方法
/**
* @JMS\Discriminator(field = "type", map = {"car": "...\Test\Car", "moped":"...\Test\Moped"})
*/
abstract class Vehicle {
public $id;
}
class Car extends Vehicle {
/**
*@JMS\Type("integer")
*/
public $id;
/**
*@JMS\Type("string")
*/
public $car_at;
/**
* @JMS\VirtualProperty
*/
public function getType()
{
return 'car';
}
}
class Moped extends Vehicle {
/**
*@JMS\Type("integer")
*/
public $id;
/**
*@JMS\Type("string")
*/
public $moped_at;
/**
* @JMS\VirtualProperty
*/
public function getType()
{
return 'moped';
}
}
class Saloon
{
/**
*@JMS\Type("integer")
*/
public $id;
/**
* @JMS\Type("...\Test\Vehicle")
*/
public $veichle;
}
//In controller
$car = new Car();
$car->id = 1;
$car->car_at = "car";
$car2 = new Moped();
$car2->id = 2;
$car2->moped_at = "moped";
$saloon = new Saloon();
$saloon->veichle = $car2;
$json = $this->get('jms_serializer')->serialize($saloon,'json');
$saloon_des = $this->get('jms_serializer')->deserialize($json,'...\Saloon','json');
仍在
The discriminator field name "type" for base-class "...\Test\Vehicle" was not found in input data.
或如果我从@JMS\Type
移除Saloon->veichle
我
The discriminator field name "type" of the base-class "...\Test\Vehicle" conflicts with a regular property of the sub-class "...\Test\Moped".
答案 0 :(得分:3)
有一个已知问题。几年前我遇到过同样的问题。我不知道他们是否解决了这个问题,但请看一下:https://github.com/schmittjoh/JMSSerializerBundle/issues/292
现在我看到jms serialzier中有这个注释:
/**
* @Discriminator(field = "type", map = {"car": "Car", "moped": "Moped"})
*/
abstract class Vehicle { }
class Car extends Vehicle { }
class Moped extends Vehicle { }
您可以设置虚拟属性,如:
class Car extends Vehicle {
/**
* @Serializer\VirtualProperty
*/
public function getType()
{
return 'car';
}
}
class Moped extends Vehicle {
/**
* @Serializer\VirtualProperty
*/
public function getType()
{
return 'moped';
}
}
尝试这种方式
答案 1 :(得分:1)
/**
* @JMS\Discriminator(field = "type", map = {
* "user": "User",
* "mod": "Moderator"
* })
*/
abstract class AbstractUser
{
/**
* @JMS\Type("integer")
*/
public $id;
/**
* @JMS\Type("string")
*/
public $name
}
class Moderator extends AbstractUser
{
/**
* @JMS\Type("string")
*/
public $foo;
}
class User extends AbstractUser
{
/**
* @JMS\Type("string")
*/
public $bar;
}
这是我的测试:
public function testSerializer()
{
$data = new Moderator();
$data->foo = 'foo';
$data->name = 'daniele';
$serializer = SerializerBuilder::create()->build();
$jsonContent = $serializer->serialize($data, 'json');
$obj = $serializer->deserialize($jsonContent, '..MyBundle\...\AbstractUser', json');
$this->assertTrue(get_class($obj), 'MyBundle....\Moderator');
}
我已经简化了命名空间,但它可以正常工作