2015-11-28 4 views
0

Я пытаюсь не десериализации это очень простой XML:XML десериализации с JMS Serializer

<?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 предупреждение ...

EDIT

Пока мне удалось решить это в глупом виде:

$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

Пожалуйста, не ставьте свой ответ на этот вопрос, сделать его ответ ниже него (даже если не идеально). Вы можете оставить вопрос открытым, чтобы сообщить, что вы все еще ищете ответ. - Или, альтернативно, обновите вопрос и уточните, каким образом ваш «рабочий» код вам недостаточен. – hakre

ответ

2

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

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

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

0

работал для меня, но не уверен, что это так:

Мой 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; 
    ... 
}