JMS序列化器:使用抽象父类进行反序列化

8
我有一个抽象的父类(映射超级类),它有几个不同属性的子类需要反序列化。我使用MongoDB和Doctrine ODM存储数据,因此我还具有鉴别器字段,告诉doctrine使用哪个子类(并且在其他地方也使用自定义的"type"属性来确定当前处理哪个类)。
当我反序列化我的模型时,我会得到一个异常,告诉我无法创建一个抽象类的实例(当然是这样)。现在我想知道如何告诉JMS Deserializer应该使用哪个继承类(例如,我使用自定义"type"实例变量 - 因为我没有访问doctrine的鉴别器字段映射)。
我可以成功地钩入preDeserializeEvent,所以也许可以在那里进行一些switch/cases操作(或者使用什么)?
我的模型简述(抽象类):
<?php 

namespace VBCMS\Bundle\AdminBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use JMS\Serializer\Annotation as Serializer;

/**
 * abstract Class Module
 * @Serializer\AccessType("public_method")
 * @MongoDB\MappedSuperclass
 * @MongoDB\InheritanceType("SINGLE_COLLECTION")
 * @MongoDB\DiscriminatorField(fieldName="_discriminator_field")
 * @MongoDB\DiscriminatorMap({
 *    "module"="Module",
 *    "text_module"="TextModule",
 *    "menu_module"="MenuModule",
 *    "image_module"="ImageModule"
 * })
 */
abstract class Module {

  const TYPE_MODULE_TEXT        = 'module.text';
  const TYPE_MODULE_MENU        = 'module.menu';
  const TYPE_MODULE_MEDIA_ITEM  = 'module.media.item';

  /**
   * @Serializer\Type("string")
   * @MongoDB\Field(type="string")
   * @var String
   */
  protected $type;

  /**
   * @Serializer\Type("boolean")
   * @MongoDB\Field(type="boolean")
   * @var boolean
   */
  protected $visible;

  // getter/setter methods etc..
}

?>

其中一个子类

<?php
namespace VBCMS\Bundle\AdminBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use JMS\Serializer\Annotation as Serializer;

/**
 * Class TextModule
 * @package VBCMS\Bundle\AdminBundle\Document
 * @Serializer\AccessType("public_method")
 * @MongoDB\EmbeddedDocument
 */
class TextModule extends Module {

    const TEXT_TYPE_SPLASH_HEADLINE = 'splashscreen.headline';
    const TEXT_TYPE_SPLASH_SUBLINE  = 'splashscreen.subline';

    /**
     * the actual text
     *
     * @var string
     * @Serializer\Type("string")
     * @MongoDB\Field(type="string")
     */
    protected $text;

    /**
     * how it is called in the admin interface
     *
     * @var string
     * @Serializer\Type("string")
     * @MongoDB\Field(type="string")
     */
    protected $label;

    /**
     * @var string
     * @Serializer\Type("string")
     * @MongoDB\Field(type="string")
     */
    protected $textType;

    // getter/setter methods etc..
?>

另一个测试是不将Module类设为抽象类,并创建自定义静态方法。
/**
 *
 * @Serializer\HandlerCallback("json", direction="deserialization")
 * @param JsonDeserializationVisitor $visitor
 */
public static function deserializeToObject(JsonDeserializationVisitor $visitor)
{
  // modify visitor somehow to return an instance of the desired inherited module class??
}

您有什么想法?


你应该将你的“更新”复制作为答案,并标记此问题已回答 - 这样其他可能遇到相同问题的人就可以清楚地看到此页面上有一个可行的解决方案。 - ioleo
1个回答

8
我在插件的测试目录中找到了一个判别映射,但很遗憾,这个功能还没有被记录下来:https://github.com/schmittjoh/serializer/blob/master/tests/JMS/Serializer/Tests/Fixtures/Discriminator/Vehicle.php 文档已更新:http://jmsyst.com/libs/serializer/master/reference/annotations#discriminator
namespace JMS\Serializer\Tests\Fixtures\Discriminator;

use JMS\Serializer\Annotation as Serializer;

/**
 * @Serializer\Discriminator(field = "type", map = {
 *    "car": "JMS\Serializer\Tests\Fixtures\Discriminator\Car",
 *    "moped": "JMS\Serializer\Tests\Fixtures\Discriminator\Moped",
 * })
 */
abstract class Vehicle
{
    /** @Serializer\Type("integer") */
    public $km;

    public function __construct($km)
    {
        $this->km = (integer) $km;
    }
}

尝试使用此进行反序列化时,我收到了“LogicError”:“基类“…”的鉴别器字段名称“...”在输入数据中未找到”。但是我不希望输入数据具有此字段。该字段仅用于克服PHP的“类型系统”。 - ironchicken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接