Десериализация XML с помощью JMS Serializer

Я пытаюсь десериализовать этот очень простой 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>

Что бы я ни пытался, я не могу десериализовать аргументы элемента в array или же ArrayCollection или любой вид коллекции, так как массив всегда заканчивается пустым.

/**
* @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;
}
);

Просто оставьте это здесь, если у кого-то есть лучше решение.

0

Решение

Вы были довольно близко Вы должны определить два отдельных класса.

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

Обратите внимание @XmlList недвижимость в Argument учебный класс. Вы можете удалить геттер и сеттер в!

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;
...
}
0

По вопросам рекламы [email protected]