我想使用 JMS Serializer 将 XML 文件反序列化为实体。
它对于直接属性非常有效。但是当涉及到嵌套属性时,如果不创建相关实体,我就无法使其工作。例如 :
<idt>
<rcs>XXXXXXX</rcs>
<name>NAME</name>
<main>
<adr_1>
<type>YYYYY</type>
<street>YYYYYYY</street>
<zip>XXXXX</zip>
</adr_1>
</main>
</idt>
我需要创建一个Idt
实体,并且反序列化可以很好地工作rcs
and name
, 但对于main
我必须创建一个Main
实体具有OneToOne
关系包含一个Adr1
实体包含type
, street
and zip
特性。这相当重。有什么方法可以告诉序列化器水合属性的路径吗?类似的东西:
class XmlRawExecutive
{
/**
* @var integer
*
* @ORM\Column(name="rcs", type="string", length=3, nullable=false)
* @JMS\Type("string")
*/
private $rcs;
/**
* @var integer
*
* @ORM\Column(name="main_adr1_street", type="integer", nullable=false)
* @JMS\Type("string")
*/
private $mainAdr1Street;
这样我就可以从 XML 中提取出一个独特的实体。
JMS Serializer 对反序列化数据映射到结果对象的方式施加了相当严格的期望。我建议使用一些更灵活的库 https://thomas.jarrand.fr/blog/serialization/对于这样的场景。
然而,即使使用 JMS Serializer,我也设法将给定的 XML 反序列化为给定的平面对象。该解决方案使用了一个pre_deserialize
事件监听器 https://jmsyst.com/libs/serializer/master/event_system,修改解析的XML数据:
use JMS\Serializer\EventDispatcher\EventDispatcher;
use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Annotation as JMS;
class Idt
{
/**
* @JMS\Type("string")
*/
protected $rcs;
/**
* @JMS\Type("string")
*/
protected $mainAdr1Street;
}
/**
* turns nested elements into children of the root element
* with names combining names of all the ancestors
*/
function recursiveChildrenInliner (\SimpleXMLElement $root, \SimpleXMLElement $child, $stack = []) {
if ($child->count() === 0) {
// produces element name like 'main_adr1_street'
$name = join('_', array_map(
function ($n) { return str_replace('_', '', $n); },
$stack
));
$root->addChild($name, $child->__toString());
} else {
foreach ($child->children() as $child) {
$stackCopy = $stack;
array_push($stackCopy, $child->getName());
recursiveChildrenInliner(
$root,
$child,
$stackCopy
);
}
}
};
// build custom serializer instance with a listener registered
$serializer = SerializerBuilder::create()
->configureListeners(function (EventDispatcher $dispatcher) {
$dispatcher->addListener('serializer.pre_deserialize',
function (PreDeserializeEvent $event) {
$data = $event->getData();
recursiveChildrenInliner($data, $data->main, ['main']);
}
);
})
->build();
$result = $serializer->deserialize($xml, Idt::class, 'xml');
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)