Сериализация графа сложного объекта в XML и обратно

1

проблема

У меня есть следующий граф объектов:

AppBundle\Controller\Person Object
(
    [name:AppBundle\Controller\Person:private] => Person Name
    [age:AppBundle\Controller\Person:private] => 10
    [phones:AppBundle\Controller\Person:private] => Array
        (
            [0] => AppBundle\Controller\Telephone Object
                (
                    [phone:AppBundle\Controller\Telephone:private] => 221-16-78
                )
            [1] => AppBundle\Controller\Telephone Object
                (
                    [phone:AppBundle\Controller\Telephone:private] => 221-16-78
                )
        )
)

и сериализация с использованием следующего кода с моего контроллера:

$s = $this->get("serializer")->serialize($person, 'xml');

и это дает мне следующий результат:

<response>
  <name>Person Name</name>
  <age>10</age>
  <phones>
    <phone>221-16-78</phone>
  </phones>
  <phones>
    <phone>221-16-78</phone>
  </phones>
</response>

Дезериализация с использованием следующего кода:

$this->get("serializer")->deserialize($s, 'AppBundle\Controller\Person', 'xml');

дает следующий ответ:

AppBundle\Controller\Person Object
(
    [name:AppBundle\Controller\Person:private] => Person Name
    [age:AppBundle\Controller\Person:private] => 10
    [phones:AppBundle\Controller\Person:private] => Array
        (
            [0] => Array
                (
                    [phone] => 221-16-78
                )
            [1] => Array
                (
                    [phone] => 221-16-78
                )
        )
)

Вопрос

Во-первых, есть способ получить xml следующим образом:

<response>
  <name>Person Name</name>
  <age>10</age>
  <phones>
    <telephone>
      <phone>221-16-78</phone>
    </telephone>
    <telephone>
      <phone>221-16-78</phone>
    </telephone>
  </phones>
</response>

И, во-вторых, как я могу десериализовать его обратно на графический объект (Person and Telephone), после использования простого десериализации он возвращает объектному человеку с массивом телефонов, который содержит ассоциативный массив вместо объектов " Telephone.

Модель/Контроллер

Здесь мои модели/контроллеры:

<?php

namespace AppBundle\Controller;

class Person {

    private $name;
    private $age;
    private $phones;

    public function getName() {
        return $this->name;
    }

    public function getAge() {
        return $this->age;
    }

    public function getPhones() {
        return $this->phones;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function setAge($age) {
        $this->age = $age;
    }

    public function setPhones($phones) {
        $this->phones = $phones;
    }

}

<?php

namespace AppBundle\Controller;

class Telephone {

    private $phone;

    public function getPhone() {
        return $this->phone;
    }

    public function setPhone($phone) {
        $this->phone = $phone;
    }

}

И мой метод контроллера:

/**
 * @Route("/", name="homepage")
 */
public function indexAction(Request $request)
{

    $phone1 = new Telephone();
    $phone1->setPhone("221-16-78");

    $phone2 = new Telephone();
    $phone2->setPhone("221-16-78");

    $person = new Person();
    $person->setName("Person Name");
    $person->setAge(10);
    $person->setPhones(array($phone1, $phone2));

    print_r($person);

    $s = $this->get("serializer")->serialize($person, 'xml');
    $p = $this->get("serializer")->deserialize($s, 'AppBundle\Controller\Person', 'xml');

    print_r($p);

}

Решение с использованием JMS Serializer

Я смог решить эту проблему с помощью JMS Serializer, предоставив некоторые подсказки для сериализатора, используя аннотации (в основном тип и список) следующим образом:

<?php

namespace AppBundle\Controller;

use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\XmlList;

class Person {

    /**
     * @Type("string")
     */
    private $name;
    /**
     * @Type("integer")
     */
    private $age;
    /**
     * @Type("array<AppBundle\Controller\Telephone>")
     * @XmlList(entry = "telephone")
     */
    private $phones;

    public function getName() {
        return $this->name;
    }

    public function getAge() {
        return $this->age;
    }

    public function getPhones() {
        return $this->phones;
    }

    public function setName($name) {
        $this->name = $name;
    }

    public function setAge($age) {
        $this->age = $age;
    }

    public function setPhones($phones) {
        $this->phones = $phones;
    }

}

<?php

namespace AppBundle\Controller;

use JMS\Serializer\Annotation\Type;

class Telephone {

    /**
     * @Type("string")
     */
    private $phone;

    public function getPhone() {
        return $this->phone;
    }

    public function setPhone($phone) {
        $this->phone = $phone;
    }

}
Теги:
serialization
xml-serialization
symfony-2.7

1 ответ

2
Лучший ответ

Насколько я понимаю, когда вы выполняете $this->get('serializer') вы получаете компонент Symfony Serialization. Я не совсем знаком с этим (вы увидите, почему в тике), но их документация действительно показывает, как обрабатывать свойства объекта, но только для сериализации.

Для типа контроля над сериализованным представлением, которое, как вам кажется, вы ищете, я бы настоятельно предложил JMS-сериализаторсвязанный пакет), который дает вам более тонкий контроль над выходом через аннотации или внешние конфиги. В вашем случае выполните:

use JMS\Serializer\Annotation as Serializer;

class Person
{
    /**
     * @Serializer\Type("array<Telephone>")
     */
    private $phones;

Может быть достаточно, чтобы получить двухстороннюю сериализацию, которую вы ищете.

  • 0
    спасибо за ваш ответ, и на самом деле он работал с использованием сериализации JMS, но ему было любопытно узнать о сериализаторе symfony2, если он не может быть использован для решения этой проблемы.
  • 0
    В большинстве случаев сериализатор Symfony идеально подходит для обслуживания, особенно если вы только сериализуете (а не десериализуете) объекты - т.е. отправляете JSON через API. Но, насколько я знаю, нет никакого способа сделать сложные преобразования с помощью способа, который позволяет сериализатор JMS, и который вам понадобится, чтобы ваш пример работал.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню