0

Je travaille sur la désérialisation d'un fichier XML. Il est possible que certains éléments ne contiennent pas de données, donc je suis en train de désérialiser l'élément XML suivant (OfferDate) dans un objet null au lieu d'un objet \DateTime:JMSSerializer: désérialisation d'un élément XML DateTime vide dans un objet PHP "null"

<Product> 
    <OfferDate></OfferDate> 
</Product> 

... mais je deviens l'erreur suivante:

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 

Si le fichier XML contiendra par exemple 2016-09-25T18:58:55 dans OfferDate cela fonctionnerait, car il y a des données ... Mais comme il est aussi possible qu'il puisse y avoir des éléments sans données que je dois impliquer ce cas aussi.

cartographie Mon YML désérialiser le XML dans un objet:

AppBundle\Domain\Model\Product: 
    xml_root_name: Product 
    properties: 
    offerDate: 
     serialized_name: OfferDate 
     type: DateTime<'Y-m-d\TH:i:s'> 

Ma Product classe:

Et enfin mon désérialisation:

$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 comme on le voit ci-dessus l'erreur est égale à la ligne $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.

est-il un moyen de désérialiser l'élément OfferDate, sans aucune donnée, dans un objet null? Et si oui, comment?

Répondre

0

J'ai créé un Handler pour le processus de désérialisation des objets DateTime.

Voici ma solution. Mon DateTimeHandler remplaçant la valeur par défaut DateHandler la classe et la méthode deserializeDateTimeFromXml fournie par le JMSSerializer:

<?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); 
    } 
} 

Puis dans mon désérialisation: (avis la méthode 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'); 

Cela fonctionne maintenant parfaitement bien!