Explorar el Código

add nullable option for xml visitor

mattw hace 12 años
padre
commit
078bbe5a27

+ 8 - 0
DependencyInjection/Configuration.php

@@ -160,6 +160,14 @@ class Configuration implements ConfigurationInterface
                         ->end()
                     ->end()
                 ->end()
+                ->children()
+                    ->arrayNode('xml')
+                        ->addDefaultsIfNotSet()
+                        ->children()
+                            ->booleanNode('serialize_null')->defaultFalse()->end()
+                        ->end()
+                    ->end()
+                ->end()
             ->end()
         ;
     }

+ 4 - 0
DependencyInjection/JMSSerializerExtension.php

@@ -153,6 +153,10 @@ class JMSSerializerExtension extends ConfigurableExtension
         $container
             ->setParameter('jms_serializer.json_serialization_visitor.serialize_null', $config['visitors']['json']['serialize_null'])
         ;
+
+        $container
+            ->setParameter('jms_serializer.xml_serialization_visitor.serialize_null', $config['visitors']['xml']['serialize_null'])
+        ;
     }
 
     public function getConfiguration(array $config, ContainerBuilder $container)

+ 3 - 0
Resources/config/services.xml

@@ -145,6 +145,9 @@
         <service id="jms_serializer.xml_serialization_visitor" class="%jms_serializer.xml_serialization_visitor.class%" public="false">
             <argument type="service" id="jms_serializer.naming_strategy" />
             <argument type="collection" /><!-- Custom Handlers -->
+            <call method="setNullable">
+                <argument>%jms_serializer.xml_serialization_visitor.serialize_null%</argument>
+            </call>
             <tag name="jms_serializer.serialization_visitor" format="xml" />
         </service>
         <service id="jms_serializer.xml_deserialization_visitor" class="%jms_serializer.xml_deserialization_visitor.class%" public="false">

+ 12 - 0
Serializer/AbstractSerializationVisitor.php

@@ -25,6 +25,18 @@ namespace JMS\SerializerBundle\Serializer;
  */
 abstract class AbstractSerializationVisitor extends AbstractVisitor
 {
+    private $nullable = false;
+
+    public function setNullable($serializeNull)
+    {
+        $this->nullable = (bool) $serializeNull;
+    }
+
+    public function isNullable()
+    {
+        return (bool) $this->nullable;
+    }
+
     public function visitUsingCustomHandler($data, $type, &$visited)
     {
         foreach ($this->customHandlers as $handler) {

+ 5 - 0
Serializer/GenericSerializationVisitor.php

@@ -78,6 +78,11 @@ abstract class GenericSerializationVisitor extends AbstractSerializationVisitor
         return $data;
     }
 
+    public function visitNull($data, $type)
+    {
+        return null;
+    }
+
     public function visitArray($data, $type)
     {
         if (null === $this->root) {

+ 3 - 4
Serializer/GraphNavigator.php

@@ -45,9 +45,6 @@ final class GraphNavigator
     {
         // determine type if not given
         if (null === $type) {
-            if (null === $data) {
-                return null;
-            }
 
             $type = gettype($data);
             if ('object' === $type) {
@@ -55,7 +52,9 @@ final class GraphNavigator
             }
         }
 
-        if ('string' === $type) {
+        if ('NULL' === $type) {
+            return $visitor->visitNull($data, $type);
+        } else if ('string' === $type) {
             return $visitor->visitString($data, $type);
         } else if ('integer' === $type) {
             return $visitor->visitInteger($data, $type);

+ 0 - 11
Serializer/JsonSerializationVisitor.php

@@ -21,7 +21,6 @@ namespace JMS\SerializerBundle\Serializer;
 class JsonSerializationVisitor extends GenericSerializationVisitor
 {
     private $options = 0;
-    private $nullable = false;
 
     public function getResult()
     {
@@ -37,14 +36,4 @@ class JsonSerializationVisitor extends GenericSerializationVisitor
     {
         $this->options = (integer) $options;
     }
-
-    public function setNullable($allowNull)
-    {
-        $this->nullable = (bool) $allowNull;
-    }
-
-    public function isNullable()
-    {
-        return (bool) $this->nullable;
-    }
 }

+ 16 - 1
Serializer/XmlSerializationVisitor.php

@@ -104,6 +104,21 @@ class XmlSerializationVisitor extends AbstractSerializationVisitor
         return $this->visitNumeric($data, $type);
     }
 
+    public function visitNull($data, $type)
+    {
+        $node = $this->document->createAttribute('xsi:nil');
+        $node->value = 'true';
+
+        if (null === $this->document) {
+            $this->document = $this->createDocument(null, null, true);
+            $this->currentNode->appendChild($this->document->appendChild($node));
+
+            return;
+        }
+
+        return $node;
+    }
+
     public function visitArray($data, $type)
     {
         if (null === $this->document) {
@@ -152,7 +167,7 @@ class XmlSerializationVisitor extends AbstractSerializationVisitor
         $v = (null === $metadata->getter ? $metadata->reflection->getValue($object)
             : $object->{$metadata->getter}());
 
-        if (null === $v) {
+        if (null === $v && !$this->isNullable()) {
             return;
         }
 

+ 5 - 4
Tests/Serializer/BaseSerializationTest.php

@@ -73,8 +73,8 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
 {
     public function testNullableArray()
     {
-        if ($this->getFormat() !== 'json') {
-            $this->markTestSkipped('nullable currently only supported by JSON');
+        if (!in_array($this->getFormat(), array('json', 'xml'))) {
+            $this->markTestSkipped('nullable currently only supported by JSON and XML');
         }
         $arr = array('foo' => 'bar', 'baz' => null, null);
         $this->assertEquals($this->getContent('nullable'), $this->getSerializer(true)->serialize($arr, $this->getFormat()));
@@ -82,8 +82,8 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
 
     public function testNullableObject()
     {
-        if ($this->getFormat() !== 'json') {
-            $this->markTestSkipped('nullable currently only supported by JSON');
+        if (!in_array($this->getFormat(), array('json', 'xml'))) {
+            $this->markTestSkipped('nullable currently only supported by JSON and XML');
         }
         $obj = new ObjectWithNullProperty('foo', 'bar');
         $this->assertEquals($this->getContent('simple_object_nullable'), $this->getSerializer(true)->serialize($obj, $this->getFormat()));
@@ -512,6 +512,7 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
 
         if ($serialize_null) {
             $serializationVisitors['json']->setNullable(true);
+            $serializationVisitors['xml']->setNullable(true);
         }
 
         $deserializationVisitors = array(

+ 6 - 0
Tests/Serializer/xml/nullable.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <entry><![CDATA[bar]]></entry>
+  <entry xsi:nil="true"/>
+  <entry xsi:nil="true"/>
+</result>

+ 7 - 0
Tests/Serializer/xml/simple_object_nullable.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <foo><![CDATA[foo]]></foo>
+  <moo><![CDATA[bar]]></moo>
+  <camel_case><![CDATA[boo]]></camel_case>
+  <null_property xsi:nil="true"/>
+</result>