2015-10-15 3 views
1

Я запускаю Symfony 2.7, и я пытаюсь вывести объект (объект Doctrine) как JSON.Обратный звонок на сериализаторе Symfony

Когда я нормализую объект, я хочу преобразовать некоторые его значения. Чтобы сделать это, я нашел метод setCallbacks в the documentation, но я немного зациклен на том, как применить его к моему делу.

Есть ли способ вызвать метод setCallbacks в нормализаторе, который задается при вызове службы сериализатора Symfonys?

Вот небольшой пример того, что я пытаюсь достичь:

//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. Кажется, что встроенный сериализатор должен иметь возможность обрабатывать то, что я пытаюсь достичь.

ответ

3

По умолчанию создается служба Serializer во время фазы впрыска зависимости, а интерфейс Serializer не позволяет редактировать (полный) поиск нормализаторов.

Я думаю, что у вас есть (по крайней мере) три выбора здесь:

  1. добавить свой собственный нормализатор в службу Serializer по умолчанию
  2. добавить NormalizableInterface своих лицам
  3. создать новую услугу 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 } 
+0

Я не тестировал код, но должен работать. Попробуйте сами и дайте мне некоторую обратную связь, если это необходимо; Я обновлю ответ для сообщества – giosh94mhz

+0

Похоже, что это может быть путь. Пример DateTime был именно тем, что они использовали в документации Symfonys. Но скажем, что в моем заказе есть набор продуктов, и мне также нужно что-то сделать с этим. Смогу ли я создать ProductNormalizer или мне как-то понадобится обработать коллекцию? Кроме того, я не совсем уверен, как применять новые нормализаторы к сервису Symfony? Я полагаю, что просто создание службы недостаточно, и у сериализатора нет метода «addNormalizer». Прошу прощения, если некоторые из них должны быть заданы. Для меня это совершенно новая территория. – Daniel

+0

@ Daniel. Процесс нормализации по умолчанию лучше всего использовать стандартную реализацию, но по умолчанию часто переводится на уродливый. Метод addNormalizer не существует (по какой-то причине), но для этого используется тег 'serializer.normalizer'. У вас может быть общий класс «MyTweeksToNormalizer», который обрабатывает несколько классов, но это может стать сложным, когда вы идете. В качестве альтернативы вы можете просто реализовать «NormalizableInterface» для всей вашей сущности. В качестве лучшего решения вы можете переключиться на «jms-serializer» и воспользоваться сериализацией, управляемой конфигурацией. – giosh94mhz

0

По-моему, вы, кажется, пытаетесь переусердствовать. Вот такой подход, который я сделал, когда мне нужно было сериализовать мои объекты как JSON:

PHP 2.5 и выше позволяет реализовать метод jsonSerialize на ваших объектах и ​​просто позвонить json_encode прямо на ваш объект.

Если вы все еще используете PHP 2.4, вам просто нужно вручную вызвать jsonSerialize() на свои объекты.

Например:

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

А затем в коде вызова:

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

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

Я бы предпочел сохранить мои сущности как можно более модульные. Текущее действие контроллера должно каким-то образом преобразовать объект, который не понадобился бы в других случаях. – Daniel

+0

О, я вижу. Да, вы не захотите загромождать класс Entity нестандартными сериализациями. – Rushing

2

Мое собственное решение

Следуя советам из giosh94mhz я попытался переключиться на JMS Serializer, но в конечном итоге происходит Вернемся к сериализатору Symfonys.

JMS Serializer представил это собственные проблемы и при поиске ответов на те, которые я наткнулся на blog post by Thomas Jarrand что сделали отличную работу, объясняя, как сделать и реализовать свои собственные нормализаторы в Symfony.

Смежные вопросы