Как настроить JMSSerializer в Symfony для сериализации пользовательского класса в / из int? - PullRequest
0 голосов
/ 27 апреля 2020

Я работаю над проектом веб-приложения на основе Symfony 3.4, который использует JMSSerializer для сериализации различных пользовательских классов в JSON для отправки этих данных в мобильные приложения.

Как я могу сериализовать / десериализовать пользовательский класс в / из int?


Предположим, у нас есть следующие классы:

<?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

Таким образом, класс NotificationInfo также имеет функцию для создать его из int и сериализовать его в in. Как сообщить сериализатору, что он должен сериализовать значение $notificationInfo в int?

Я мог бы использовать вместо этого следующее:

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

Однако в этом случае мне нужно настроить сериализацию NotificationInfo, где я могу только указать, какое свойство должно сериализоваться, к какому значению ...


РЕДАКТИРОВАТЬ:

Это - JSON, который я хотел бы создать:

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

Это то, что я НЕ ищу:

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

Ответы [ 2 ]

0 голосов
/ 29 апреля 2020

После долгих поисков я нашел следующее решение для своей проблемы: я добавил пользовательскую сериализацию Handler, которая сообщает JMSSerializer, как обрабатывать мой пользовательский класс:

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());
    }

}

Благодаря autowire обработчик добавляется автоматически и может использоваться в метаданных сериализатора:

notificationInfo:
    type: NotificationInfo
    expose: true
0 голосов
/ 28 апреля 2020

Вы можете использовать метод VirtualProperty, чтобы добавить любой метод вашего класса в json response

use JMS\Serializer\Annotation as Serializer;

class NotificationInfo 
{
    /**
     * @return int
     * @Serializer\VirtualProperty()
     * @Serializer\SerializedName("formatedLocation")
     */
    public function toInt()
    {
        return 4272020;
    }
}
...