gpt4 book ai didi

jmsserializerbundle - 使用 JMSSerializer 格式化输入和输出字段(处理单个属性)

转载 作者:行者123 更新时间:2023-12-04 17:22:13 25 4
gpt4 key购买 nike

我想使用 JMSSerializer 处理序列化和反序列化的单个对象属性。假设我们有这个类:

class Task {

const STATUS_PENDING = 0;
const STATUS_OVER = 1;

protected $status;

/* getter and setter */

public function getStatusLabel()
{
return ['pending', 'over'][$this->getStatus()];
}

public static function getStatusFromLabel($label)
{
return [
'pending' => self::STATUS_PENDING,
'over' => self::STATUS_OVER
][$label];
}
}

我想返回一个抛出 REST API 的 Task 实例(使用 FOSRestBundle)。问题是我不想返回 $status 的原始值属性,而是“标签”值。

像这样配置我的序列化:
Task:
exclusion_policy: ALL
properties:
status:
expose: true
type: string

JMS Serializer 考虑 0 或 1 的原始值,但我想在我的序列化对象中发送 'pending' 或 'over'(使用 getStatusLabel )。并在反序列化上做相反的工作(使用 getStatusFromLabel )。

我想到了一个 virtual_properties但它仅适用于序列化方向。

我尝试使用如下所示的自定义处理程序:

class TaskHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return [
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => 'Task',
'method' => 'serializeToArray',
]
];
}

public function serializeToArray(JsonSerializationVisitor $visitor, Task $task, array $type, Context $context)
{
$task->setStatus($task->getStatusLabel());
return $visitor->getNavigator()->accept($task, $type, $context);
}

但它显然不起作用!

我怎么能在序列化和反序列化方向上调用我的自定义 setter/getter ?

最佳答案

我终于找到了答案。

首先,我必须创建一个这样的事件订阅者:

use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;

class TaskSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
[
'event' => Events::PRE_SERIALIZE,
'format' => 'json',
'class' => 'Task', // fully qualified name here
'method' => 'onPreSerializeTaskJson',
],
[
'event' => Events::PRE_DESERIALIZE,
'format' => 'json',
'class' => 'Task',
'method' => 'onPreDeserializeTaskJson',
]
];
}

public function onPreSerializeTaskJson(PreSerializeEvent $event)
{
/** @var Task $task */
$task = $event->getObject();

$task->setStatus($task->getStatusLabel());
}

public function onPreDeserializeTaskJson(PreDeserializeEvent $event)
{
$data = $event->getData();

$data['status'] = Task::getStatusFromLabel($data['status']);

$event->setData($data);
}
}

我在这里做什么:
  • 在序列化之前,我使用标签
  • 设置了我的 Task 对象的状态值。
  • 在反序列化之前,我将序列化对象的值从标签更改为原始整数值

  • 对于此解决方案,必须将字段( expose: true@Expose )暴露给序列化程序。

    然后我在 Symfony 中将订阅者声明为服务,标签为 jms_serializer.event_subscriber .
    serializer.subscriber.task:
    class: %serializer.subscriber.task.class% # TaskSubscriber class path
    tags:
    - { name: jms_serializer.event_subscriber }

    它有效。

    这是我发现的序列化和反序列化的最佳方式。也可以操作 post_serialize 和 post_deserialize 事件上的数据。例如,在序列化对象上添加一个新字段:

    use JMS\Serializer\EventDispatcher\ObjectEvent;

    public function onPostSerializeTaskJson(ObjectEvent $event)
    {
    /** @var Task $task */
    $task = $event->getObject();

    $event->getVisitor()->addData('nb_related', count($task->getRelatedTasks()));
    }

    关于jmsserializerbundle - 使用 JMSSerializer 格式化输入和输出字段(处理单个属性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20687489/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com