简体   繁体   English

串行器Symfony上的回调

[英]Callback on serializer Symfony

I'm running Symfony 2.7 and I'm trying output an object (Doctrine entity) as JSON. 我正在运行Symfony 2.7,我正在尝试输出一个对象(Doctrine实体)作为JSON。

When I'm normalizing the object I want to convert some of it's values. 当我正在标准化对象时,我想转换它的一些值。 To do this I found the "setCallbacks" method in the documentation but I'm kinda stumped on how to apply it to my case. 为此,我在文档中找到了“setCallbacks”方法,但我对如何将其应用于我的案例感到困惑。

Is there any way to call the "setCallbacks" method on the normalizer that is set when calling Symfonys serializer service? 有没有办法在调用Symfonys序列化服务器时设置的规范化器上调用“setCallbacks”方法?

Here is a short example of what I'm trying to achieve: 这是我想要实现的一个简短示例:

//ExampleController.php

public function getJSONOrderByIdAction($id) {
    $serializer = $this->get('serializer');
    $normalizer = $serializer->getNormalizer(); // <- This is what I'm unable to do

    $dateTimeToString = function ($dateTime) {
        return $dateTime instanceof \DateTime ? $dateTime->format(\DateTime::ISO8601) : '';
    };

    $normalizer->setCallbacks(['time' => $dateTimeToString]);


    $order = $this->getDoctrine()->find("AppBundle:Order", $id);

    return new JsonResponse(["order" => $serializer->normalize($order, null, ["groups" => ["public"]])]);
}

I'm aware that most people have switched to the JMS serializer. 我知道大多数人已经切换到JMS序列化器。 It just seems as if the built in serializer should be able to handle what I'm trying to achieve. 看起来好像内置的序列化程序应该能够处理我想要实现的内容。

The default Serializer service is created during dependency injection phase, and the Serializer interface do not allow editing of (full) retrieval of normalizers. 默认的Serializer服务是在依赖注入阶段创建的,而Serializer接口不允许编辑规范器的(完整)检索。

I think you have (at least) three choice here: 我想你在这里有(至少)三种选择:

  1. add your custom normalizer to the default Serializer service 将自定义规范化程序添加到默认的Serializer服务
  2. add NormalizableInterface to your entities 将NormalizableInterface添加到您的实体
  3. create a new Serializer service (or a local object as suggested by the docs) as you were trying to do. 按照您的尝试创建一个新的Serializer服务(或文档建议的本地对象)。

I think in your scenario, case 1 is preferred (since 2 becomes boring pretty fast). 我认为在你的场景中,情况1是首选(因为2变得很无聊很快)。

I would do something like this; 我会做这样的事情; first create a custom Normalizer 首先创建一个自定义规范器

<?php
namespace AppBundle; 

class DateTimeNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface
{
    /**
     * {@inheritdoc}
     */
    public function normalize($object, $format = null, array $context = array())
    {
        return $object->format(\DateTime::ISO8601);
    }

    /**
     * {@inheritdoc}
     */
    public function denormalize($data, $class, $format = null, array $context = array())
    {
        return new $class($data);
    }

    /**
     * Checks if the given class is a DateTime.
     *
     * @param mixed  $data   Data to normalize.
     * @param string $format The format being (de-)serialized from or into.
     *
     * @return bool
     */
    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof \DateTime;
    }

    /**
     * Checks if the given class is a DateTime.
     *
     * @param mixed  $data   Data to denormalize from.
     * @param string $type   The class to which the data should be denormalized.
     * @param string $format The format being deserialized from.
     *
     * @return bool
     */
    public function supportsDenormalization($data, $type, $format = null)
    {
        $class = new \ReflectionClass($type);

        return $class->isSubclassOf('\DateTime');
    }
}

Then register it to your services: 然后将其注册到您的服务:

# app/config/services.yml
services:
    datetime_normalizer:
        class: AppBundle\DateTimeNormalizer
        tags:
            - { name: serializer.normalizer }

My own solution 我自己的解决方案

Following the advice from giosh94mhz I tried switching to JMS Serializer but ended up going back to Symfonys serializer. 根据giosh94mhz的建议,我尝试切换到JMS Serializer但最终回到Symfonys序列化器。

JMS Serializer presented it's own issues and while searching for answers for those I stumbled upon a blog post by Thomas Jarrand that did an excellent job explaining how to make and implement your own normalizers in Symfony. JMS Serializer提出了它自己的问题,在搜索那些我偶然发现Thomas Jarrand博客文章的答案时,他们在Symfony中解释了如何制作实现自己的规范化程序。

In my opinion, you seem to be trying to over-complicate things. 在我看来,你似乎试图使事情过于复杂。 Here's the approach I've taken when I needed to serialize my entities as JSON: 这是我在需要将实体序列化为JSON时采用的方法:

PHP 2.5 and above allows you to implement the jsonSerialize method on your objects and just call json_encode directly on your object. PHP 2.5及更高版本允许您在对象上实现jsonSerialize方法,并直接在对象上调用json_encode

If you are still using PHP 2.4, you just need to manually call jsonSerialize() on your objects. 如果您仍在使用PHP 2.4,则只需在对象上手动调用jsonSerialize()

For example: 例如:

/**
 * @ORM\Entity
 */
class MyEntity {
    ...
    public function jsonSerialize() {
        $data = array("foo" => $this->bar());
        // add other data here ...
        return $data
    }
}

And then in calling code: 然后在调用代码时:

// for PHP 2.5 and up:
$normalized = json_encode($myEntityInstance);

// for PHP 2.4 and below
$normalized = json_encode($myEntityInstance->jsonSerialize());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM