【问题标题】:XML deserialization with JMS Serializer使用 JMS 序列化器进行 XML 反序列化
【发布时间】:2016-03-02 10:32:44
【问题描述】:

我正在尝试反序列化这个非常简单的 XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <namespace>foo</namespace>
    <resource>bar</resource>
    <description>baz</description>
    <arguments>
        <argument>
            <name>foo</name>
            <type>string</type>
            <description>foo</description>
        </argument>
        <argument>
            <name>bar</name>
            <type>string</type>
            <description>bar</description>
        </argument>
    </arguments>
</root>

无论我尝试什么,我都无法将 arguments 元素反序列化为 arrayArrayCollection 或任何类型的集合,因为数组始终为空。

/**
 * @Type("array<Model\Argument>")
 */
private $arguments;

/**
 * @Type("ArrayCollection<Model\Argument>")
 */
private $arguments;

两者都以空数组结束。所以我尝试为参数创建一个单独的对象

因此原始属性最终为

/**
 * @Type("Model\Arguments")
 */
private $arguments;

和班级

class Arguments {
    /**
     * @Type("array<App\Blueprint\Model\Argument>")
     */
    private $arguments;

    /**
     * @return mixed
     */
    public function getArguments() {
        return $this->arguments;
    }

    /**
     * @param mixed $arguments
     */
    public function setArguments($arguments) {
        $this->arguments = $arguments;
    }
}

数组仍然是空的。但是,当我将类型更改为 @Type("App\Blueprint\Model\Argument") 时,我会得到正确的对象,尽管只有第一个。

当我尝试注册一个反序列化处理程序时,我无法修改它,因为它以 SimpleXmlElement 的形式出现,然后我会收到 It is not yet possible to assign complex types to properties 警告...

编辑

现在我设法以一种愚蠢的方式解决了它:

$registry->registerHandler(
    'deserialization',
    'Model\Arguments',
    'xml',
    function(XmlDeserializationVisitor $visitor, $data, array $type, DeserializationContext $context) {
        $arguments = [];
        foreach($data->children() as $child) {
            $arguments[] = SerializerBuilder::create()
                ->build()
                ->deserialize($child->asXML(), 'Model\Argument', 'xml');
        }

        return $arguments;
    }
);

如果有人有更好的解决方案,请在此处省略。

【问题讨论】:

  • 请不要将您的答案放在问题中,将其作为其下方的答案(即使不完美)。您可以让问题保持开放状态,以表明您仍在寻找答案。 -- 或者更新问题并明确说明您的“工作”代码对您来说是不够的。

标签: php xml symfony serialization jms-serializer


【解决方案1】:

你很接近。您必须定义两个单独的类。

/**
 * @Type("Model\Arguments")
 */
public $arguments;
/**
 * @Type("array<Model\Argument>")
 * @XmlList(inline = true, entry = "argument")
 */
public $argument;

注意Argument 类中的@XmlList 属性。您也可以删除 getter 和 setter!

【讨论】:

  • "inline = true" 标志很重要!
【解决方案2】:

为我工作,但不确定是不是这样:

我的 XML:

<activityData>
    <count>1</count>
    <facts>
        <fact>
            <dateTime year="2016" month="11" day="14" hour="0" minute="0" second="0" />
            <channel>Administrator</channel>
            <count>1</count>
        </fact>
    </facts>
</activityData>

还有我的模特:

1.

class ActivityData
{
    /**
     * @var ArrayCollection|ActivityDataFact[]
     *
     * @Serializer\Type("ArrayCollection<AppBundle\Model\ActivityDataFact>")
     * @Serializer\XmlList(entry="fact")
     */
    private $facts;
    ...
}

2.

class ActivityDataFact
{
    /**
     * @var DateTime
     *
     * @Serializer\Type("AppBundle\Model\DateTime")
     * @Serializer\SerializedName("dateTime")
     */
    private $date;

    /**
     * @var string
     *
     * @Serializer\Type("string")
     */
    private $channel;

    /**
     * @var integer
     *
     * @Serializer\Type("integer")
     */
    private $count;
    ...
}

3.

class DateTime
{
    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $year = 1970;

    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $month = 1;

    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $day = 1;

    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $hour = 0;

    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $minute = 0;

    /**
     * @var string
     *
     * @Serializer\Type("integer")
     * @Serializer\XmlAttribute()
     */
    private $second = 0;
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 2016-07-25
    • 2021-12-13
    • 2021-05-08
    • 1970-01-01
    相关资源
    最近更新 更多