php - JMS 序列化程序。创建 2 种具有 "one-to-many"关系的模型序列化方式

标签 php jms-serializer

我正在使用 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)
    )
);

这里我展示了我的代码的简化示例。我用它来存储订单更改的历史记录。在更新之前和之后,我将这个序列化模型保存到数据库中。好的。

现在我想用所有属性序列化产品的模型,以便在客户端工作。所以我的第一个想法是使用组。我需要为 $id 和 $name 属性设置“Group({'history', 'edit'})”以及所有其他“Group({'edit'})”。好的,它适用于产品序列化,但它会破坏第一个解决方案。现在我的“订单历史记录”存储了不必要的信息,例如 $price 和 $description。

是否有一些正确的方法来指定产品模型的默认组,如果未隐式指定序列化组(如订单的历史示例),将使用该默认组?或通过某种其他方式使这两种类型的序列化可用,而无需将组移动到 Order 的模型中(因为实际上在这种情况下应该重构的模型不止一个)。

最佳答案

对不起。我发现如果我使用“默认”组,一切正常。

<?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 序列化器 :)

关于php - JMS 序列化程序。创建 2 种具有 "one-to-many"关系的模型序列化方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22145198/

相关文章:

symfony - 使用 JMSSerializerBundle 序列化指定字段

php - 不常见的 502 Bad Gateway 错误

php - 无法将参数传递给 Symfony 3.3 中的服务

json - 如何删除 symfony json 中的代理字段

php - 使用 JMS Serializer 反序列化混合类型的值

symfony - FOSElastica 为什么我的结果没有序列化?

php - curl 错误 : Warning: curl_exec(): 45 is not a valid cURL handle resource

javascript - 刷新留言箱

php - 使用 phpunit 测试命令 symfony

symfony - 如何为 JMS Serializer 创建自定义排除策略,以便我可以在运行时决定是否包含特定字段?