ale*_*x88 37 serialization symfony jmsserializerbundle
我有一个实体,我通常使用JMS Serializer包进行序列化.我必须在序列化中添加一些字段,这些字段不驻留在实体本身中,而是通过一些数据库查询收集.
我的想法是创建一个自定义对象,用实体字段填充字段并添加自定义对象.但是对于每个变体(我使用很多序列化组)而言,这似乎有点棘手且昂贵.
有没有更好/标准的方法来做到这一点?用工厂?前/后序列化事件?
也许我可以监听序列化并检查实体类型和序列化组添加自定义字段?但是,不是对每个实体进行查询,而是收集相关实体的所有数据然后将其添加到它们中更好.任何帮助表示赞赏
ale*_*x88 71
我自己找到了解决方案,
在序列化完成后添加自定义字段我们要创建一个这样的监听器类:
<?php
namespace Acme\DemoBundle\Listener;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\Tag;
use JMS\DiExtraBundle\Annotation\Inject;
use JMS\DiExtraBundle\Annotation\InjectParams;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Acme\DemoBundle\Entity\Team;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\JsonSerializationVisitor;
/**
* Add data after serialization
*
* @Service("acme.listener.serializationlistener")
* @Tag("jms_serializer.event_subscriber")
*/
class SerializationListener implements EventSubscriberInterface
{
/**
* @inheritdoc
*/
static public function getSubscribedEvents()
{
return array(
array('event' => 'serializer.post_serialize', 'class' => 'Acme\DemoBundle\Entity\Team', 'method' => 'onPostSerialize'),
);
}
public function onPostSerialize(ObjectEvent $event)
{
$event->getVisitor()->addData('someKey','someValue');
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以将数据添加到序列化元素.
相反,如果要在序列化之前编辑对象,请使用pre_serialize事件,请注意,如果要使用pre_serialize添加值,则需要已有变量(以及正确的序列化组).
Jam*_*wuh 15
我很惊讶为什么没有人提出更简单的方法.你只需要使用@VirtualProperty:
<?php
// ...
/**
* @JMS\VirtualProperty
* @JMS\SerializedName("someField")
*/
public function getSomeField()
{
return $this->getTitle() . $this->getPromo();
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*nes 10
进一步回答原来的问题.以下是限制某些序列化组的添加数据的方法(在此示例some_data中仅在我们不使用该list组时添加:
public function onPostSerializeSomeEntityJson(ObjectEvent $event) {
$entity = $event->getObject();
if (!in_array('list', (array)$event->getContext()->attributes->get('groups'))) {
$event->getVisitor()->addData('user_access', array(
'some_data' => 'some_value'
));
}
}
Run Code Online (Sandbox Code Playgroud)
(array)$event->getContext()->attributes->get('groups') 包含使用的序列化组的数组.
接受的答案仅在访客来自时才有效\JMS\Serializer\GenericSerializationVisitor.这意味着它适用于JSON,但对XML不适用.
这是一个处理XML的示例方法.它查看访问者对象支持的接口并正确地执行操作.它显示了如何向JSON和XML序列化对象添加链接元素......
public function onPostSerialize(ObjectEvent $event)
{
//obtain some data we want to add
$link=array(
'rel'=>'self',
'href'=>'http://example.org/thing/1',
'type'=>'application/thing+xml'
);
//see what our visitor supports...
$visitor= $event->getVisitor();
if ($visitor instanceof \JMS\Serializer\XmlSerializationVisitor)
{
//do XML things
$doc=$visitor->getDocument();
$element = $doc->createElement('link');
foreach($link as $name => $value) {
$element->setAttribute($name, $value);
}
$doc->documentElement->appendChild($element);
} elseif ($visitor instanceof \JMS\Serializer\GenericSerializationVisitor)
{
$visitor->addData('link', $link);
}
}
Run Code Online (Sandbox Code Playgroud)
addData 从 2.0.0 开始已被弃用,所以我们需要这样做:
use JMS\Serializer\EventDispatcher\ObjectEvent;
class MySerializerHandler {
public function onPostSerialize(ObjectEvent $event)
{
/** @var MySpecialObjectType $object */
$myObject = $event->getObject();
$key = 'customDataKey';
$value = 'myvalue';
$event->getVisitor()->visitProperty(
new StaticPropertyMetadata('', $key, $value),
$value
);
}
}
Run Code Online (Sandbox Code Playgroud)
服务.yaml
services:
MySerializerHandler:
tags:
- { name: jms_serializer.event_listener, class: 'MySpecialObjectType', event: serializer.post_serialize, method: 'onPostSerialize' }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23499 次 |
| 最近记录: |