在 JMS 序列化程序中排除空属性

Exclude null properties in JMS Serializer

我使用的 XML API 有一个选项可以只检索部分响应。 如果使用此功能,这会导致生成的对象具有很多 NULL 属性。 有没有办法真正跳过 NULL 属性?我尝试使用

实施排除策略
shouldSkipProperty(PropertyMetadata $property, Context $context)`

但我意识到无法访问当前的 属性 值。

示例如下class

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
    }
]

您可以配置 JMS 序列化程序以跳过 null 属性,如下所示:

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

摘自 this issue.

更新:

不幸的是,如果您在反序列化时不想要空属性,除了自己删除它们之外别无他法。

但是,我不确定您实际想要删除这些属性的用例是什么,但看起来 Hotel class 不包含太多逻辑。在这种情况下,我想知道结果是否应该是 class ?

我认为将数据表示为关联数组而不是对象会更自然。当然,JMS Serializer 无法将您的数据反序列化为数组,因此您将需要一个数据传输对象。

dumpArrayloadArray 方法添加到现有 Hotel class 就足够了。这些将用于将数据转换为您想要的结果,反之亦然。有你的DTO。

/**
 * Sets the object's 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
}

我认为这是最干净的方法,它可能反映出您正在尝试做更多的事情。

希望对您有所帮助。