PankovAlxndr
@PankovAlxndr
Fullstack web developer

Как через jms/serializer десериализовать null?

Здравствуйте
использую библиотеку jms/serializer

документация вот
https://jmsyst.com/libs/serializer/master/referenc...

есть некое api оно возвращает xml
иногда так бывает что атрибут какого-то элемента не установлен
примерно так
<element id="3" zone="" period="1-2" />

у меня есть php класс, экземпляр которого я получаю десерализуя xml строку
в этом классе через аннотации мапятся свойства экземпляра на данные xml
все работает как надо НО
я имею такую конструкцию (кусочек)
/**
 * @JMS\XmlRoot("element")
 */
final class Element
{
    /**
     * @JMS\XmlAttribute()
     */
    private ?int $zone = null;
}


много опущено, но суть в том что zone="" десериализуется в 0(int)
не могу нагуглить и понять как мне объяснить сериализатору, что так делать не надо

в коде серализатора нашел
// Sometimes data can convey null but is not of a null type.
// Visitors can have the power to add this custom null evaluation
if ($this->visitor instanceof NullAwareVisitorInterface && true === $this->visitor->isNull($data)) {
 $type = ['name' => 'NULL', 'params' => []];
}


вроде как он понимает NULL но не могу найти как это описать? (как выбирается visitor)
  • Вопрос задан
  • 264 просмотра
Решения вопроса 1
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
а как он задает приватное свойство?
типы свойств jmsyst.com/libs/serializer/master/reference/annota...
как вариант
final class Element
{
    /**
     * @XmlAttribute
     */
    private ?int $zone = null;
    public function __set(string $name, $value)
    {
           if ($name === 'zone' && $value === 0) {
                 $value = null;
           }
           $this->{$name} = $value;
    }
}

или
final class Element
{
    /**
     * @XmlAttribute
     */
    private ?int $zone = null;

    public function __get(string $name)
    {
           if ($name === 'zone' && $this->zone === 0) {
                 return null;
           }
           return $this->{$name};
    }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
gzhegow
@gzhegow
aka "ОбнимиБизнесмена"
Там два способа есть.

Один - если перечитать документацию Symfony\Serializer (который расширяется уже нашим JMS) там есть настройка типа Allow Serialize Nulls что-то такое, когда-то искал. Есть еще парочка типа "предельный уровень вложенности" и тд.

Но по мне симфонийский или другой сериалайзер из коробки такая себе игрушка. Обычно прошу полдня (а первый раз ушатал неделю) на его оборачивание в большое число обработчиков, ведь сериализация ИЗ json в данные должна проходить по имеющимся PhpDoc\TypedProperty, а сериализация обратно желательно по Yaml-файлам, которые вам легко редактировать и где легче задавать условия что выдавать и когда. Ну ларавелисты вот ресурсы плодят, чтобы указывать какие поля когда можно делать, а симфонисты Yaml файлы редактируют так легче.

Но и тут есть проблема. Некоторые вещи должны появится не тогда когда вы передадите с фронта им "группу" для вывода (там есть группа, которая типа условие), а тогда когда к ним доступ имеется (например сумма на счете ваших друзей видна админу или самому другу, но не вам). Ларавелисты в этот момент вешаются, ведь им надо во все ресурсы теперь добавлять IF и думать как туда сунуть сервис, который доступ дает. У симфонистов проще. Они в контроллере пишут "IF (что-то) addGroup()" но это подразумевает, что вас сериализер - это сервис, который синглтоном (да, простите, шарным сервисом в контейнере) доступен где захочется, чтобы группу можно было не только из фронтенда передать, но и динамически присобачить.

То есть к вопросу сериализации Null я бы подходил оч комплексно на тему создания MySerializer/MyDeserializer где проверял бы ифами "а мона или нуна".
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы