JMSSerializer:将空 DateTime XML 元素反序列化为 PHP "null" 对象
JMSSerializer: Deserializing empty DateTime XML element into PHP "null" object
我正在处理 XML 文件的反序列化。某些元素可能不包含任何数据,因此我尝试将以下 XML 元素 (OfferDate
) 反序列化为 null
对象而不是 \DateTime
对象:
<Product>
<OfferDate></OfferDate>
</Product>
...但出现以下错误:
JMS\Serializer\Exception\RuntimeException: Invalid datetime "", expected format Y-m-d\TH:i:s.
./vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php:117
./vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php:99
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:180
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:280
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:236
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:175
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:130
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:251
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:236
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:182
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:116
./vendor/phpoption/phpoption/src/PhpOption/Some.php:89
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:119
./tests/AppBundle/Domain/Model/ProductTest.php:35
./tests/AppBundle/Domain/Model/ProductTest.php:44
如果 XML 文件包含例如 OfferDate
中的 2016-09-25T18:58:55
它会起作用,因为有一些数据......但是因为也可能有元素没有数据我也得牵涉到这个案子
我的 YML 映射将 XML 反序列化为一个对象:
AppBundle\Domain\Model\Product:
xml_root_name: Product
properties:
offerDate:
serialized_name: OfferDate
type: DateTime<'Y-m-d\TH:i:s'>
我的Product
class:
<?php
declare(strict_types = 1);
namespace AppBundle\Domain\Model;
/**
* @author ...
*/
class Product
{
/**
* @var \DateTime
*/
private $offerDate;
/**
* @return \DateTime
*/
public function getOfferDate(): \DateTime
{
return $this->offerDate;
}
}
最后是我的反序列化:
$xml = file_get_contents(__DIR__.'/product.xml');
$serializer = SerializerBuilder::create()
->addMetadataDir(__DIR__.'/../../../../app/config/serializer')
->build();
/** @var ProductCollection $productCollection */
$productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
$firstProduct = $productCollection->getProducts()[0];
var_dump($firstProduct->getOfferDate());
./tests/AppBundle/Domain/Model/ProductTest.php:35
如上所示,错误等于行 $productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
.
To clarify why I deserialize into a ProductCollection
:
The product.xml
contains a <Products>
element in which <Product>
elements are. The ProductCollection
then contains a method called getProducts()
which returns an array containing the deserialized Product
objects.
有没有办法将没有任何数据的 OfferDate
元素反序列化为 null
对象?如果是这样,怎么做?
我想出了为 DateTime 对象的反序列化过程创建 Handler。
这是我的解决方案。我的 DateTimeHandler
覆盖了 JMSSerializer 提供的默认 DateHandler
s class 和方法 deserializeDateTimeFromXml
:
<?php
declare(strict_types = 1);
namespace AppBundle\Serializer\Handler;
use JMS\Serializer\Handler\DateHandler;
use JMS\Serializer\XmlDeserializationVisitor;
/**
* @author ...
*/
class DateTimeHandler extends DateHandler
{
/**
* @param XmlDeserializationVisitor $visitor
* @param $data
* @param array $type
*
* @return \DateTime|null
*/
public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
{
// Casting the data to a string will return the value of the
// current xml element. So if it's empty there is no data.
if ((string)$data === '') {
return null;
}
return parent::deserializeDateTimeFromXml($visitor, $data, $type);
}
}
然后在我的反序列化中:(注意 configureHandlers
方法)
$xml = file_get_contents(__DIR__.'/product.xml');
$serializer = SerializerBuilder::create()
->addMetadataDir(__DIR__.'/../../../../app/config/serializer')
->configureHandlers(
function (HandlerRegistry $registry) {
$registry->registerSubscribingHandler(new DateTimeHandler());
}
)
->build();
/** @var ProductCollection $productCollection */
$productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
这现在工作得很好!
我正在处理 XML 文件的反序列化。某些元素可能不包含任何数据,因此我尝试将以下 XML 元素 (OfferDate
) 反序列化为 null
对象而不是 \DateTime
对象:
<Product>
<OfferDate></OfferDate>
</Product>
...但出现以下错误:
JMS\Serializer\Exception\RuntimeException: Invalid datetime "", expected format Y-m-d\TH:i:s.
./vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php:117
./vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php:99
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:180
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:280
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:236
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:175
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:130
./vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php:251
./vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.php:236
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:182
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:116
./vendor/phpoption/phpoption/src/PhpOption/Some.php:89
./vendor/jms/serializer/src/JMS/Serializer/Serializer.php:119
./tests/AppBundle/Domain/Model/ProductTest.php:35
./tests/AppBundle/Domain/Model/ProductTest.php:44
如果 XML 文件包含例如 OfferDate
中的 2016-09-25T18:58:55
它会起作用,因为有一些数据......但是因为也可能有元素没有数据我也得牵涉到这个案子
我的 YML 映射将 XML 反序列化为一个对象:
AppBundle\Domain\Model\Product:
xml_root_name: Product
properties:
offerDate:
serialized_name: OfferDate
type: DateTime<'Y-m-d\TH:i:s'>
我的Product
class:
<?php
declare(strict_types = 1);
namespace AppBundle\Domain\Model;
/**
* @author ...
*/
class Product
{
/**
* @var \DateTime
*/
private $offerDate;
/**
* @return \DateTime
*/
public function getOfferDate(): \DateTime
{
return $this->offerDate;
}
}
最后是我的反序列化:
$xml = file_get_contents(__DIR__.'/product.xml');
$serializer = SerializerBuilder::create()
->addMetadataDir(__DIR__.'/../../../../app/config/serializer')
->build();
/** @var ProductCollection $productCollection */
$productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
$firstProduct = $productCollection->getProducts()[0];
var_dump($firstProduct->getOfferDate());
./tests/AppBundle/Domain/Model/ProductTest.php:35
如上所示,错误等于行 $productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
.
To clarify why I deserialize into a
ProductCollection
: Theproduct.xml
contains a<Products>
element in which<Product>
elements are. TheProductCollection
then contains a method calledgetProducts()
which returns an array containing the deserializedProduct
objects.
有没有办法将没有任何数据的 OfferDate
元素反序列化为 null
对象?如果是这样,怎么做?
我想出了为 DateTime 对象的反序列化过程创建 Handler。
这是我的解决方案。我的 DateTimeHandler
覆盖了 JMSSerializer 提供的默认 DateHandler
s class 和方法 deserializeDateTimeFromXml
:
<?php
declare(strict_types = 1);
namespace AppBundle\Serializer\Handler;
use JMS\Serializer\Handler\DateHandler;
use JMS\Serializer\XmlDeserializationVisitor;
/**
* @author ...
*/
class DateTimeHandler extends DateHandler
{
/**
* @param XmlDeserializationVisitor $visitor
* @param $data
* @param array $type
*
* @return \DateTime|null
*/
public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
{
// Casting the data to a string will return the value of the
// current xml element. So if it's empty there is no data.
if ((string)$data === '') {
return null;
}
return parent::deserializeDateTimeFromXml($visitor, $data, $type);
}
}
然后在我的反序列化中:(注意 configureHandlers
方法)
$xml = file_get_contents(__DIR__.'/product.xml');
$serializer = SerializerBuilder::create()
->addMetadataDir(__DIR__.'/../../../../app/config/serializer')
->configureHandlers(
function (HandlerRegistry $registry) {
$registry->registerSubscribingHandler(new DateTimeHandler());
}
)
->build();
/** @var ProductCollection $productCollection */
$productCollection = $serializer->deserialize($xml, ProductCollection::class, 'xml');
这现在工作得很好!