Skip to content

Commit

Permalink
Moved isNullData away to a separate NullEvaluatorInterface
Browse files Browse the repository at this point in the history
Only the XMLDeserializationVisitor implements the `NullEvaluatorInterface`
Restored behaviour in the GraphNavigator for the SerializationContext (elseif branch)
Removed now obsolete tests from the BaseSerializationTest
  • Loading branch information
pbouwdewijn committed May 22, 2017
1 parent e4b5d82 commit 1f9021e
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 46 deletions.
10 changes: 0 additions & 10 deletions src/AbstractVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,4 @@ protected function getElementType($typeArray)
return $typeArray['params'][0];
}
}

/**
* @param mixed $data
*
* @return bool
*/
public function isNullData($data)
{
return $data === null;
}
}
12 changes: 10 additions & 2 deletions src/GraphNavigator.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,18 @@ public function accept($data, array $type = null, Context $context)

$type = array('name' => $typeName, 'params' => array());
}

// If the data is null, we have to force the type to null regardless of the input in order to
// guarantee correct handling of null values, and not have any internal auto-casting behavior.
if ($visitor instanceof VisitorInterface && true === $visitor->isNullData($data)) {
else if ($context instanceof SerializationContext && null === $data) {
$type = array('name' => 'NULL', 'params' => array());
}

// Sometimes data can convey null but is not of a null type.
// Visitors can have the power to add this custom null evaluation
if ($visitor instanceof VisitorInterface
&& $visitor instanceof NullEvaluatorInterface
&& $visitor->evaluatesToNull($data) === true
) {
$type = array('name' => 'NULL', 'params' => array());
}

Expand Down
32 changes: 32 additions & 0 deletions src/NullEvaluatorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* Copyright 2016 Johannes M. Schmitt <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace JMS\Serializer;

interface NullEvaluatorInterface
{
/**
* Determine if a value conveys a null value.
* An example could be an xml element (Dom, SimpleXml, ...) that is tagged with a xsi:nil attribute
*
* @param mixed $value
*
* @return bool
*/
public function evaluatesToNull($value);
}
10 changes: 0 additions & 10 deletions src/VisitorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,4 @@ public function getNavigator();
* @return object|array|scalar
*/
public function getResult();

/**
* Determine if the value evaluates to null.
* Used by the navigator to determine the correct data type.
*
* @param mixed $data
*
* @return bool
*/
public function isNullData($data);
}
15 changes: 6 additions & 9 deletions src/XmlDeserializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

class XmlDeserializationVisitor extends AbstractVisitor
class XmlDeserializationVisitor extends AbstractVisitor implements NullEvaluatorInterface
{
private $objectStack;
private $metadataStack;
Expand Down Expand Up @@ -389,24 +389,21 @@ private function getDomDocumentTypeEntitySubset($data)
}

/**
* Consider xml element value null if the xsi:nil attribute is set and therefore can't have a value
* @see https://www.w3.org/TR/xmlschema-1/#xsi_nil
*
* @param $data
* @param mixed $value
*
* @return bool
*/
public function isNullData($data)
public function evaluatesToNull($value)
{
if ($data instanceof \SimpleXMLElement) {
$xsiAttributes = $data->attributes('http://www.w3.org/2001/XMLSchema-instance');
if ($value instanceof \SimpleXMLElement) {
$xsiAttributes = $value->attributes('http://www.w3.org/2001/XMLSchema-instance');

//We have to keep the isset quiet, some tests give error: `Node no longer exists`; even though it evaluates to false
if (@isset($xsiAttributes['nil']) && (string) $xsiAttributes['nil'] === 'true') {
return true;
}
}

return $data === null;
return $value === null;
}
}
13 changes: 0 additions & 13 deletions tests/Serializer/BaseSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1364,19 +1364,6 @@ public function testObjectWithNullableArrays()
$this->assertEquals($this->getContent('nullable_arrays'), $this->serializer->serialize($object, $this->getFormat()));
}

public function testIsNullDataWithNull()
{
/** @var VisitorInterface $visitor */
foreach ($this->serializationVisitors as $visitor) {
$this->assertTrue($visitor->isNullData(null));
}

/** @var VisitorInterface $visitor */
foreach ($this->deserializationVisitors as $visitor) {
$this->assertTrue($visitor->isNullData(null));
}
}

abstract protected function getContent($key);

abstract protected function getFormat();
Expand Down
5 changes: 3 additions & 2 deletions tests/Serializer/XmlSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,14 @@ public function testDeserializeEmptyString()
$this->deserialize('', 'stdClass');
}

public function testIsNullDataWithXSINilLabeledElement()
public function testEvaluatesToNull()
{
$namingStrategy = $this->getMockBuilder(PropertyNamingStrategyInterface::class)->getMock();
$visitor = new XmlDeserializationVisitor($namingStrategy);
$element = simplexml_load_string('<empty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>');

$this->assertTrue($visitor->isNullData($element));
$this->assertTrue($visitor->evaluatesToNull($element));
$this->assertTrue($visitor->evaluatesToNull(null));
}

private function xpathFirstToString(\SimpleXMLElement $xml, $xpath)
Expand Down

0 comments on commit 1f9021e

Please sign in to comment.