Исключить свойства null в JMS Serializer

Мой использованный XML API имеет возможность извлекать только части ответа. Это приводит к тому, что результирующий объект имеет много свойств NULL, если эта функция используется. Есть ли способ пропустить свойства NULL? Я попытался реализовать стратегию исключения с помощью

shouldSkipProperty(PropertyMetadata $property, Context $context)`

но я понял, что нет способа получить доступ к текущему значению свойства.

Примером может служить следующий класс

class Hotel {
    /**
     * @Type("string")
     */
    public $id;

    /**
     * @Type("integer")
     */
    public $bookable;

    /**
     * @Type("string")
     */
    public $name;

    /**
     * @Type("integer")
     */
    public $type;

    /**
     * @Type("double")
     */
    public $stars;

    /**
     * @Type("MssPhp\Schema\Response\Address")
     */
    public $address;

    /**
     * @Type("integer")
     */
    public $themes;

    /**
     * @Type("integer")
     */
    public $features;

    /**
     * @Type("MssPhp\Schema\Response\Location")
     */
    public $location;

    /**
     * @Type("MssPhp\Schema\Response\Pos")
     */
    public $pos;

    /**
     * @Type("integer")
     */
    public $price_engine;

    /**
     * @Type("string")
     */
    public $language;

    /**
     * @Type("integer")
     */
    public $price_from;
}

который десериализует этот конкретный вызов api для следующего объекта с большим количеством свойств NULL.

"hotel": [
    {
        "id": "11230",
        "bookable": 1,
        "name": "Hotel Test",
        "type": 1,
        "stars": 3,
        "address": null,
        "themes": null,
        "features": null,
        "location": null,
        "pos": null,
        "price_engine": 0,
        "language": "de",
        "price_from": 56
    }
]

Но я хочу, чтобы он был

"hotel": [
    {
        "id": "11230",
        "bookable": 1,
        "name": "Hotel Test",
        "type": 1,
        "stars": 3,
        "price_engine": 0,
        "language": "de",
        "price_from": 56
    }
]

Ответ 1

Вы можете настроить JMS Serializer для пропуска следующих свойств null:

$serializer = JMS\SerializerBuilder::create();              
$serializedString = $serializer->serialize(
    $data,
    'xml',
    JMS\SerializationContext::create()->setSerializeNull(true)
);

Взято из этот вопрос.

UPDATE:

К сожалению, если вы не хотите пустые свойства при десериализации, нет другого пути, кроме как удалить их самостоятельно.

Однако я не уверен, что ваш вариант использования для фактического желания удалить эти свойства, но не похоже, что класс Hotel содержит много логики. В этом случае мне интересно, должен ли результат быть классом вообще?

Я думаю, что было бы более естественно иметь данные, представленные как ассоциативный массив, а не объект. Конечно, JMS Serializer не может десериализовать ваши данные в массиве, поэтому вам понадобится объект передачи данных.

Достаточно, чтобы вы добавили методы dumpArray и loadArray в существующий класс Hotel. Они будут использоваться для преобразования данных в ваш желаемый результат и наоборот. Существует ваш DTO.

/**
 * Sets the object properties based on the passed array
 */
public function loadArray(array $data)
{
}

/**
 * Returns an associative array based on the objects properties
 */
public function dumpArray()
{
    // filter out the properties that are empty here
}

Я считаю, что это самый чистый подход, и он может отражать то, что вы пытаетесь сделать больше.

Надеюсь, это поможет.