Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

symfony 3 normalizer for json - format all Timestamps

Tags:

json

php

symfony

In my Symfony 3 app, I'm using a normalizer and a serializer to format a result set as JSON. By default all the doctrine Datetimes are rendered in the format:

"maintenanceStart":{
 "timezone":{"name":"Australia\/Melbourne",
 "location":{"country_code":"AU","latitude":-37.81667,"longitude":144.96666,
 "comments":"Victoria"}},
 "offset":36000,"timestamp":1372892400}

I can output this in an ISO date format on a per-field basis by setting a callback on the normalizer as follows:

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

    $normalizer->setCallbacks ( array (
            'maintenanceStart' => $callback 
    ) );

But I'd like to apply this change to all Timestamps without having to specify each field. Is there a straightforward way to do this?

Entity definition:

/**
 * @var \DateTime
 *
 * @ORM\Column(name="MAINTENANCE_START", type="datetime", nullable=true)
 */
private $maintenanceStart;

Controller code:

public function dataAction(Request $request) {

    $doc = $this->get ( 'doctrine' );
    $repo = $doc->getRepository ( 'AppBundle:Customer' );
    $result = $repo->createQueryBuilder ( 'c' )->getQuery ()->getResult ();

    $encoder = new JsonEncoder ();
    $normalizer = new GetSetMethodNormalizer ();

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

    $normalizer->setCallbacks ( array (
            'maintenanceStart' => $callback 
    ) );

    $serializer = new Serializer ( array (
            $normalizer, new \AppBundle\DateTimeNormalizer() 
    ), array (
            $encoder 
    ) );

    $json = $serializer->serialize ( $result, 'json' );

    return $this->render ( 'default/data.json.twig', [ 
            'data' => $json,
            'base_dir' => realpath ( $this->getParameter ( 'kernel.root_dir' ) . '/..' ) 
    ] );
}
like image 935
Black Avatar asked Apr 11 '16 22:04

Black


2 Answers

In trying to follow the prescribed method (posted here https://stackoverflow.com/a/33149890/403614), I neglected to observe that the Array of Normalizers passed into the Serializer is order-dependent.

So, the problem and fix for my code above is to reverse the order so that the DateTime Normalizer applies first:

$normalizer = new GetSetMethodNormalizer ();
$serializer = new Serializer ( array (
         new \AppBundle\DateTimeNormalizer(), $normalizer
), array (
        $encoder 
) );
like image 74
Black Avatar answered Sep 19 '22 04:09

Black


You can create your own normalizer, and declare it as a service.

You can use the exact code of the response: https://stackoverflow.com/a/33149890/403614

like image 34
magnetik Avatar answered Sep 22 '22 04:09

magnetik