我正在尝试使用Symfony创建一个简单的日历。为此,我想通过AJAX请求所选月份的事件。每个事件都可以连接多个用户。
现在检索事件非常简单
$events = $this->em->getRepository('AppBundle:Event')
->findByYearMonth($this->getUser(), $year, $month);
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getId();
});
$serializer = new Serializer([$normalizer], [$encoder]);
$serialized = $serializer->serialize($events, 'json');
$response = new Response($serialized);
$response->headers->set('Content-Type', 'application/json');
我需要setCircularReferenceHandler
,因为显然用户也有与之相关的事件。
在我的测试中,我目前只有2个事件,但我得到了~50kb的响应,只是因为它被用户对象臃肿了。我真正想要的只是用户ID和名称,但它会检索所有其他字段(以及其他连接的实体)。
循环引用处理程序本身仅在用户返回后才会激活(并在最初检索用户的用户中捕获事件)。
我已经搜索了这个,但没有找到一个按照我想要的方式进行的结果(大多数是关于表格,一般序列化等)。
我唯一的想法是向Event实体添加一个方法,例如getSimple
,我手动设置一些参数并将其输出(但必须为连接的所有内容执行此操作)。这看起来很不干净,因此我在这里问。
TL; DR
我想要像
这样的东西[
{"id":1, "name":"foo", "users":[
{"id":1, "name":hans"},
{"id":2, "name":"jack"},...
]},...
]
但我有点像
[
{"id":1, "name":"foo", "users":[
{"id":1, "name":hans", "events":[1,{"id":3, "name":"this hasnt already been shown"}], "userfield":"var", "anotheruserfield":"bar", "someOtherRelation":{"bla"},
{"id":2, "name":"jack", "events":[1,{"id":3, "name":"this hasnt already been shown"}], "userfield":"var", "anotheruserfield":"bar", "someOtherRelation":{"bla"}},...
]},...
]
答案 0 :(得分:0)
如果我正确理解,您希望从对象序列化中排除class Foo
{
public int Bar { get; set; }
}
var source = new List<Foo>();
bool test1 = !source.Any() || source.All(e => e.Bar == 0);
bool test2 = source.All(e => e.Bar == 0);
bool test3 = !source.Any(e => e.Bar == 0);
Debug.Assert(test1 == test2 && test2 == test3);
属性(可能还有其他属性)。
JMSSerializer可以满足您的需求,因为它允许排除/暴露属性和/或限制其深度。
在Symfony文档的Serialization chapter末尾提到了该包。
请参阅exclusion strategies及其events
,@Exclude
,@Expose
和@Groups
注释。
答案 1 :(得分:0)
是的,JMSSerializer提供了Exclude
和其他可能解决此问题的方法,但我决定采用不同的方法:编写一个自定义EventNormalizer
,它完全符合我的要求并且不会改变另一个实体本身。
$encoder = new JsonEncoder();
$normalizer = new \AppBundle\Serializer\Normalizer\EventNormalizer();
$serializer = new Serializer([$normalizer], [$encoder]);
$serialized = $serializer->serialize($events, 'json');
和规范化器
namespace AppBundle\Serializer\Normalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
* Event normalizer
*/
class EventNormalizer implements NormalizerInterface
{
/**
* {@inheritdoc}
*/
public function normalize($object, $format = null, array $context = array())
{
$result = /* using fields from $object */
return $result;
}
/**
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = null)
{
return $data instanceof \AppBundle\Entity\Event;
}
}