symfonyjms-serializer

How configure JMSSerializer in Symfony to serialize custom class to/from int?


I am working on a Symfony 3.4 based web app project which uses JMSSerializer to serialize different custom classes to JSON to send this data to mobile apps.

How can I serialize/deserialize a custom class to/from to int?


Assume we have the following classes:

<?php

// AppBundle/Entity/...

class NotificationInfo {
    public $date;      // DateTime
    public $priority;  // Int 1-10
    public $repeates;  // Boolean

    public function toInt() {
        // Create a simple Int value
        //  date = 04/27/2020
        //  priority = 5
        //  repeats = true
        //  ==> int value = 4272020 5 1 = 427202051
    }

    public function __construnct($intValue) {
       // ==> Split int value into date, priority and repeats...
    }
}


class ToDoItem {
    public $title;
    public $tags;
    public $notificationInfo;
}


// AppBundle/Resources/config/serializer/Entiy.ToDoItem.yml
AppBundle\Entity\ToDoItem:
exclusion_policy: ALL
properties:
    title:
        type: string
        expose: true
    tags:
        type: string
        expose: true
    notificationInfo:
        type: integer
        expose: true

So the class NotificationInfo also has function to create it from int and to serialize it to in. How to tell the serializer that it should serialize the value of $notificationInfo to int?

I could use the following instead:

    notificationInfo:
        type: AppBundle\Entity\NotificationInfo
        expose: true

However in this case I need to configure the serialization of NotificationInfo where I can only specify which property should serialized to which value...


EDIT:

This is the JSON I would like to create:

{
    "title": "Something ToDO",
    "tags": "some,tags",
    "notificationInfo": 427202051
}

This is what I am NOT looking for:

{
    "title": "Something ToDO",
    "tags": "some,tags",
    "notificationInfo": {
        "intValue": 427202051
    }
}

Solution

  • After a lot more digging I found the following solution for my problem: I added a custom serialization Handler which tells JMSSerializer how to handle my custom class:

    class NotificationInfoHandler implements SubscribingHandlerInterface {
    
        public static function getSubscribingMethods() {
            return [
                [
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'format' => 'json',
                    'type' => 'NotificationInfo',
                    'method' => 'serializeNotificationInfoToJson',
                ],
                [
                    'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                    'format' => 'json',
                    'type' => 'NotificationInfo',
                    'method' => 'deserializeNotificationInfoToJson',
                ],
            ;
    
    
        public function serializeNotificationInfoToJson(JsonSerializationVisitor $visitor, NotificationInfo $info, array $type, Context $context) {
            return $info->toInt();
        }
    
        public function deserializeNotificationInfoToJson(JsonDeserializationVisitor $visitor, $infoAsInt, array $type, Context $context) {
            return (is_int($infoAsInt) ? NotificationInfo::fromInt($infoAsInt) : NotificationInfo::emptyInfo());
        }
    
    }
    

    Thanks to autowire the handler is automatically added and can be used in the serializer metadata:

    notificationInfo:
        type: NotificationInfo
        expose: true