我正在运行Symfony 2.7,并且正在尝试将对象(Doctrine实体)输出为JSON。

当我规范化对象时,我想转换它的一些值。为此,我在the documentation中找到了“ setCallbacks”方法,但是我对如何将其应用于我的案例有些困惑。

有什么方法可以在调用Symfonys序列化程序服务时在所设置的规范化器上调用“ setCallbacks”方法?

这是我要实现的简短示例:

//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"]])]);
}


我知道大多数人都已切换到JMS序列化器。似乎内置的序列化程序应该能够处理我要实现的目标。

最佳答案

默认的Serializer服务是在依赖项注入阶段创建的,并且Serializer接口不允许编辑(完全)规范化器。

我认为您至少有三个选择:


将您的自定义规范化器添加到默认的Serializer服务
将NormalizableInterface添加到您的实体
按照您的尝试创建一个新的Serializer服务(或文档建议的本地对象)。


我认为在您的情况下,情况1是首选的(因为2变得非常无聊)。

我会做这样的事情;首先创建一个自定义的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');
    }
}


然后将其注册到您的服务中:

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

10-01 15:38