Сериализатор JMS. Создайте 2 способа сериализации модели, которые имеют отношения «один ко многим».

Я использую JMS Serializer для проекта PHP и наткнулся на одну проблему.

Посмотрите на код

<?php
use JMS\Serializer\Annotation as Serializer;

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Order
{
    /**
     * @var int
     * @Serializer\Type("integer")
     * @Serializer\Expose
     */
    private $id;

    /**
     * @var Product[]
     * @Serializer\Type("array<Product>")
     * @Serializer\Expose
     */
    private $products;

    /**
     * @var float
     * @Serializer\Type("float")
     * @Serializer\Expose
     */
    private $total;

    private $someInternalProperty;

    function __construct($products)
    {
        $this->id = rand(0, 100);
        $this->products = $products;
        $this->total = rand(100, 1000);
        $this->someInternalProperty = 'Flag';
    }
}

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Product
{
    /**
     * @var int
     * @Serializer\Type("integer")
     * @Serializer\Expose
     */
    private $id;

    /**
     * @var string
     * @Serializer\Type("string")
     * @Serializer\Expose
     */
    private $name;

    private $price;

    private $description;

    function __construct($id, $name, $price, $description)
    {
        $this->id = $id;
        $this->name = $name;
        $this->price = $price;
        $this->description = $description;
    }
}

$order = new Order([
    new Product(
        1,
        'Banana',
        10,
        'Yellow'
    ),
    new Product(
        2,
        'Tomato',
        12,
        'Red'
    )
]);

$serializer = \JMS\Serializer\SerializerBuilder::create()
    ->setPropertyNamingStrategy(new \JMS\Serializer\Naming\SerializedNameAnnotationStrategy(new \JMS\Serializer\Naming\IdenticalPropertyNamingStrategy()))
    ->build();

print_r(
    $serializer->serialize(
        $order,
        'json',
        \JMS\Serializer\SerializationContext::create()
            ->setSerializeNull(true)
    )
);

Здесь я показал упрощенный пример моего кода. Я использую его для хранения истории изменений заказа. До и после обновления я сохраняю эту сериализованную модель в базу данных. Ok.

И теперь я хочу сериализовать модель продукта со всеми свойствами для работы на стороне клиента. Итак, первая идея, которая у меня возникла, — использовать группы. Мне нужно установить для свойств $id и $name "Группа ({'история', 'редактирование'})" и для всех остальных "Группа ({'редактирование'})". Хорошо, это работает для сериализации продукта, но портит первое решение. Теперь моя «история заказов» хранит ненужную информацию, такую ​​как $price и $description.

Есть ли правильный способ указать группу по умолчанию для модели продукта, которая будет использоваться, если группа сериализации не указана неявно (как в примере с историей заказов)? Или какой-либо другой способ сделать эти два типа сериализации доступными без перемещения групп в модель Order (поскольку в действительности в этом случае необходимо реорганизовать более одной модели).


person Victor Lopez    schedule 03.03.2014    source источник


Ответы (1)


Извиняюсь. Я обнаружил, что все работает правильно, если я использую группу «По умолчанию».

<?php

require_once __DIR__ . '/../../../app/Autoload.php';

use JMS\Serializer\Annotation as Serializer;

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Order
{
    /**
     * @var int
     * @Serializer\Type("integer")
     * @Serializer\Expose
     */
    private $id;

    /**
     * @var Product[]
     * @Serializer\Type("array<Product>")
     * @Serializer\Expose
     */
    private $products;

    /**
     * @var float
     * @Serializer\Type("float")
     * @Serializer\Expose
     */
    private $total;

    private $someInternalProperty;

    function __construct($products)
    {
        $this->id = rand(0, 100);
        $this->products = $products;
        $this->total = rand(100, 1000);
        $this->someInternalProperty = 'Flag';
    }
}

/**
 * @Serializer\ExclusionPolicy("all")
 */
class Product
{
    /**
     * @var int
     * @Serializer\Expose
     * @Serializer\Type("integer")
     * @Serializer\Groups({"Default", "edit"})
     */
    private $id;

    /**
     * @var string
     * @Serializer\Expose
     * @Serializer\Type("string")
     * @Serializer\Groups({"Default", "edit"})
     */
    private $name;

    /**
     * @Serializer\Expose
     * @Serializer\Groups({"edit"})
     */
    private $price;

    /**
     * @Serializer\Expose
     * @Serializer\Groups({"edit"})
     */
    private $description;

    private $hiddenProperty;

    function __construct($id, $name, $price, $description)
    {
        $this->id = $id;
        $this->name = $name;
        $this->price = $price;
        $this->description = $description;
        $this->hiddenProperty = 42;
    }
}

$product1 = new Product(
    1,
    'Banana',
    10,
    'Yellow'
);

$order = new Order([
    $product1,
    new Product(
        2,
        'Tomato',
        12,
        'Red'
    )
]);

$serializer = \JMS\Serializer\SerializerBuilder::create()
    ->setPropertyNamingStrategy(new \JMS\Serializer\Naming\SerializedNameAnnotationStrategy(new \JMS\Serializer\Naming\IdenticalPropertyNamingStrategy()))
    ->build();

print_r([
    $serializer->serialize(
        $order,
        'json',
        \JMS\Serializer\SerializationContext::create()
            ->setSerializeNull(true)
            ->setGroups(['Default'])
    ),
    $serializer->serialize(
        $product1,
        'json',
        \JMS\Serializer\SerializationContext::create()
            ->setSerializeNull(true)
            ->setGroups(['edit'])
    ),

]);

И вот результат:

Array
(
    [0] => {"id":86,"products":[{"id":1,"name":"Banana"},{"id":2,"name":"Tomato"}],"total":644} // Here I have short model for history
    [1] => {"id":1,"name":"Banana","price":10,"description":"Yellow"} // And here I have expanded model for other purpose.
)

Я люблю JMS-сериализатор :)

person Victor Lopez    schedule 04.03.2014
comment
ДА! У меня была группа с именем «по умолчанию», и я изменил ее на «По умолчанию». Теперь это работает. Это ожидаемое поведение? - person mineroot; 28.06.2017
comment
в документации не вижу информации о чувствительности к регистру для групп, но тест говорит сам за себя - person Victor Lopez; 10.07.2017