在JMS Serializer中排除null属性

时间:2016-04-05 14:45:25

标签: php null jms xml-deserialization 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 个答案:

答案 0 :(得分:3)

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

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

取自this issue

<强>更新

不幸的是,如果您在反序列化时不想要空属性,则没有其他方法可以自行删除它们。

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

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

您可以将dumpArrayloadArray方法添加到现有的Hotel课程中。这些将用于将数据转换为您想要的结果,反之亦然。有你的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
}

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

我希望这会有所帮助。