Десериализовать XML в Entity с вложенными узлами, используя JMS Serializer - PullRequest
0 голосов
/ 11 мая 2018

Я хочу десериализовать файл XML в сущность с помощью JMS Serializer.Это работает довольно хорошо для прямых свойств.Но когда дело доходит до вложенных свойств, я не могу заставить его работать без создания связанных сущностей.Например:

<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 и name, но для main мне нужно создать Mainсущность с отношением OneToOne, содержащая сущность Adr1, содержащую свойства type, street и 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.

1 Ответ

0 голосов
/ 09 августа 2018

JMS Serializer налагает довольно строгие ожидания на то, как десериализованные данные отображаются в результирующие объекты.Я бы предложил использовать некоторую более гибкую библиотеку для подобных сценариев.

Однако мне удалось десериализовать данный XML в заданный плоский объект даже с помощью JMS Serializer.В решении используется pre_deserialize прослушиватель событий , модифицирующий проанализированные данные 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');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...