如何在 Symfony 2.0 AJAX 应用程序中将 Doctrine 实体编码为 JSON?
我正在开发游戏应用程序并使用 Symfony 2.0。我有很多对后端的 AJAX 请求。更多的响应是将实体转换为 JSON。例如:
class DefaultController extends Controller
{
public function launchAction()
{
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->find($id);
// encode user to json format
$userDataAsJson = $this->encodeUserDataToJson($user);
return array(
'userDataAsJson' => $userDataAsJson
);
}
private function encodeUserDataToJson(User $user)
{
$userData = array(
'id' => $user->getId(),
'profile' => array(
'nickname' => $user->getProfile()->getNickname()
)
);
$jsonEncoder = new JsonEncoder();
return $jsonEncoder->encode($userData, $format = 'json');
}
}
我的所有控制器都做同样的事情:获取一个实体并将其一些字段编码为 JSON。我知道我可以使用规范化器并对所有实体进行编码。但是,如果一个实体具有到其他实体的循环链接怎么办?或者实体图很大?您有什么建议吗?
我考虑一些实体的编码模式...或使用 NormalizedInterface
来避免循环...,
I'm developing game app and using Symfony 2.0. I have many AJAX requests to the backend. And more responses is converting entity to JSON. For example:
class DefaultController extends Controller
{
public function launchAction()
{
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->find($id);
// encode user to json format
$userDataAsJson = $this->encodeUserDataToJson($user);
return array(
'userDataAsJson' => $userDataAsJson
);
}
private function encodeUserDataToJson(User $user)
{
$userData = array(
'id' => $user->getId(),
'profile' => array(
'nickname' => $user->getProfile()->getNickname()
)
);
$jsonEncoder = new JsonEncoder();
return $jsonEncoder->encode($userData, $format = 'json');
}
}
And all my controllers do the same thing: get an entity and encode some of its fields to JSON. I know that I can use normalizers and encode all entitities. But what if an entity has cycled links to other entity? Or the entities graph is very big? Do you have any suggestions?
I think about some encoding schema for entities... or using NormalizableInterface
to avoid cycling..,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
现在使用 php5.4 你可以这样做:
然后调用
With php5.4 now you can do :
And then call
另一种选择是使用 JMSSerializerBundle。然后,在控制器中,
您可以使用实体类中的注释来配置序列化的完成方式。请参阅上面链接中的文档。例如,以下是排除链接实体的方法:
Another option is to use the JMSSerializerBundle. In your controller you then do
You can configure how the serialization is done by using annotations in the entity class. See the documentation in the link above. For example, here's how you would exclude linked entities:
您可以使用以下方法自动编码为 Json,您的复杂实体:
You can automatically encode into Json, your complex entity with:
为了完成答案:Symfony2 附带了一个 json_encode 的包装器:
Symfony/Component/HttpFoundation/JsonResponse
控制器中的典型用法:
To complete the answer: Symfony2 comes with a wrapper around json_encode:
Symfony/Component/HttpFoundation/JsonResponse
Typical usage in your Controllers:
我发现序列化实体问题的解决方案如下:
在我的控制器中:
其他示例:
您甚至可以将其配置为反序列化 http://api.symfony.com/2.0
I found the solution to the problem of serializing entities was as follows:
in my controller:
other example:
you can even configure it to deserialize arrays in http://api.symfony.com/2.0
我只需要解决同样的问题:对一个实体(“用户”)进行 json 编码,该实体与另一个实体(“位置”)具有一对多双向关联。
我尝试了几件事,我想现在我找到了最好的可接受的解决方案。这个想法是使用与 David 编写的相同的代码,但以某种方式通过告诉规范化器在某个点停止来拦截无限递归。
我不想实现自定义规范化器,因为在我看来,这个 GetSetMethodNormalizer 是一个很好的方法(基于反射等)。因此,我决定对其进行子类化,乍一看这并不简单,因为表示是否包含属性的方法 (isGetMethod) 是私有的。
但是,人们可以重写规范化方法,因此我在这一点上进行了拦截,只需取消设置引用“位置”的属性即可,因此无限循环被中断。
在代码中它看起来像这样:
I just had to solve the same problem: json-encoding an entity ("User") having a One-To-Many Bidirectional Association to another Entity ("Location").
I tried several things and I think now I found the best acceptable solution. The idea was to use the same code as written by David, but somehow intercept the infinite recursion by telling the Normalizer to stop at some point.
I did not want to implement a custom normalizer, as this GetSetMethodNormalizer is a nice approach in my opinion (based on reflection etc.). So I've decided to subclass it, which is not trivial at first sight, because the method to say if to include a property (isGetMethod) is private.
But, one could override the normalize method, so I intercepted at this point, by simply unsetting the property that references "Location" - so the inifinite loop is interrupted.
In code it looks like this:
我遇到了同样的问题,我选择创建自己的编码器,它将通过递归来自行应对。
我创建了实现
Symfony\Component\Serializer\Normalizer\NormalizerInterface
的类,以及一个包含每个NormalizerInterface
的服务。规范化器的示例:
在控制器中:
完整的代码在这里:https://github.com/progracqteur/WikiPedale/tree/master/src/Progracqteur/WikipedaleBundle/Resources/Normalizer
I had the same problem and I chosed to create my own encoder, which will cope by themself with recursion.
I created classes which implements
Symfony\Component\Serializer\Normalizer\NormalizerInterface
, and a service which holds everyNormalizerInterface
.An example of a Normalizer :
In a controller :
The complete code is here : https://github.com/progracqteur/WikiPedale/tree/master/src/Progracqteur/WikipedaleBundle/Resources/Normalizer
在 Symfony 2.3
/app/config/config.yml
和控制器示例中:
但是字段类型 \DateTime 的问题仍然存在。
in Symfony 2.3
/app/config/config.yml
and example for your controller:
but the problems with the field type \DateTime will remain.
这更多的是一个更新(对于 Symfony v:2.7+ 和 JmsSerializer v:0.13.*@dev),以避免 Jms 尝试加载和序列化整个对象图(或者在循环的情况下)关系..)
模型:
在动作内部:
This is more an update (for Symfony v:2.7+ and JmsSerializer v:0.13.*@dev), so to avoid that Jms tries to load and serialise the whole object graph ( or in case of cyclic relation ..)
Model:
Inside an Action:
如果您使用 Symfony 2.7 或更高版本,并且不想包含任何额外的序列化包,也许您可以按照这种方式将学说实体序列化为 json -
在我的(常见的,父)控制器,我有一个准备序列化器的函数
然后用它来将实体序列化为 JSON
完成!
但您可能需要一些微调。例如 -
If you are using Symfony 2.7 or above, and don't want to include any additional bundle for serializing, maybe you can follow this way to seialize doctrine entities to json -
In my (common, parent) controller, I have a function that prepares the serializer
Then use it to serialize Entities to JSON
Done!
But you may need some fine tuning. For example -
当您需要在 Symfony 上创建大量 REST API 端点时,
最好的方法是使用以下捆绑包堆栈:
正确配置所有内容后,实体代码将如下所示:
然后,控制器中的代码:
这种设置的好处是:
@JMS\Expose()
注释添加到简单的字段,以及任何类型的关系。此外,还可以公开某些方法执行的结果(使用注释@JMS\VirtualProperty())@ApiDoc()
允许直接从浏览器测试端点,无需任何 REST 客户端或 JavaScript 代码When you need to create a lot of REST API endpoints on Symfony,
the best way is to use the following stack of bundles:
When you configure everything properly, you entity code will look like this:
Then, code in controller:
The benefits of such a set up are:
@JMS\Expose()
annotations in the entity can be added to simple fields, and to any type of relations. Also, there is the possibility to expose the result of some method execution (use annotation@JMS\VirtualProperty()
for that)@ApiDoc()
allows testing the endpoint directly from the browser, without any REST client or JavaScript code现在,您还可以使用 Doctrine ORM 转换 将实体转换为嵌套标量数组并返回
Now you can also use Doctrine ORM Transformations to convert entities to nested arrays of scalars and back
接受的答案是正确的,但如果您需要序列化 Entity 的过滤子集, json_encode 就足够了:
考虑这个例子:
简短说明:至少在 Symfony 5.1 上测试
The accepted answer is correct but if You'll need to serialize a filtered subset of an Entity , json_encode is enough:
Consider this example:
Short note: Tested at least on Symfony 5.1