浏览代码

Merge pull request #201 from iwf-web/issue-199

fix issue #199: "array" type ignoring DateTime format
Johannes 11 年之前
父节点
当前提交
c93adad8a3

+ 18 - 0
src/JMS/Serializer/AbstractVisitor.php

@@ -38,4 +38,22 @@ abstract class AbstractVisitor implements VisitorInterface
     {
         return $data;
     }
+
+    /**
+     * @param array $typeArray
+     */
+    protected function getElementType($typeArray)
+    {
+        if (false === isset($typeArray['params'][0])) {
+            return null;
+        }
+
+        if (isset($typeArray['params'][1]) && is_array($typeArray['params'][1])) {
+            return $typeArray['params'][1];
+        }
+        else {
+            return $typeArray['params'][0];
+        }
+    }
+
 }

+ 1 - 1
src/JMS/Serializer/GenericSerializationVisitor.php

@@ -99,7 +99,7 @@ abstract class GenericSerializationVisitor extends AbstractVisitor
         }
 
         foreach ($data as $k => $v) {
-            $v = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context);
+            $v = $this->navigator->accept($v, $this->getElementType($type), $context);
 
             if (null === $v && (!is_string($k) || !$context->shouldSerializeNull())) {
                 continue;

+ 1 - 1
src/JMS/Serializer/XmlSerializationVisitor.php

@@ -171,7 +171,7 @@ class XmlSerializationVisitor extends AbstractVisitor
                 $entryNode->setAttribute($keyAttributeName, (string) $k);
             }
 
-            if (null !== $node = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context)) {
+            if (null !== $node = $this->navigator->accept($v, $this->getElementType($type), $context)) {
                 $this->currentNode->appendChild($node);
             }
 

+ 1 - 1
src/JMS/Serializer/YamlSerializationVisitor.php

@@ -96,7 +96,7 @@ class YamlSerializationVisitor extends AbstractVisitor
 
             $this->writer->indent();
 
-            if (null !== $v = $this->navigator->accept($v, null, $context)) {
+            if (null !== $v = $this->navigator->accept($v, $this->getElementType($type), $context)) {
                 $this->writer
                     ->rtrim(false)
                     ->writeln(' '.$v)

+ 63 - 0
tests/JMS/Serializer/Tests/Fixtures/DateTimeArraysObject.php

@@ -0,0 +1,63 @@
+<?php
+/*
+ * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * 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\Tests\Fixtures;
+
+use JMS\Serializer\Annotation\Type;
+use JMS\Serializer\Annotation\XmlMap;
+use JMS\Serializer\Annotation\XmlList;
+use JMS\Serializer\Annotation\XmlKeyValuePairs;
+
+
+class DateTimeArraysObject
+{
+    /**
+     * @var \DateTime[]
+     * @Type("array<DateTime>")
+     */
+    private $arrayWithDefaultDateTime;
+
+    /**
+     * @var \DateTime[]
+     * @Type("array<DateTime<'d.m.Y H:i:s'>>")
+     */
+    private $arrayWithFormattedDateTime;
+
+
+    function __construct($arrayWithDefaultDateTime, $arrayWithFormattedDateTime)
+    {
+        $this->arrayWithDefaultDateTime    = $arrayWithDefaultDateTime;
+        $this->arrayWithFormattedDateTime  = $arrayWithFormattedDateTime;
+    }
+
+    /**
+     * @return \DateTime[]
+     */
+    public function getArrayWithDefaultDateTime()
+    {
+        return $this->arrayWithDefaultDateTime;
+    }
+
+    /**
+     * @return \DateTime[]
+     */
+    public function getArrayWithFormattedDateTime()
+    {
+        return $this->arrayWithFormattedDateTime;
+    }
+
+}

+ 47 - 0
tests/JMS/Serializer/Tests/Fixtures/NamedDateTimeArraysObject.php

@@ -0,0 +1,47 @@
+<?php
+/*
+ * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * 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\Tests\Fixtures;
+
+use JMS\Serializer\Annotation\Type;
+use JMS\Serializer\Annotation\XmlMap;
+use JMS\Serializer\Annotation\XmlList;
+use JMS\Serializer\Annotation\XmlKeyValuePairs;
+
+
+class NamedDateTimeArraysObject
+{
+    /**
+     * @var \DateTime[]
+     * @Type("array<string,DateTime<'d.m.Y H:i:s'>>")
+     * @XmlKeyValuePairs
+     */
+    private $namedArrayWithFormattedDate;
+
+    function __construct($namedArrayWithFormattedDate)
+    {
+        $this->namedArrayWithFormattedDate = $namedArrayWithFormattedDate;
+    }
+
+    /**
+     * @return \DateTime[]
+     */
+    public function getNamedArrayWithFormattedDate()
+    {
+        return $this->namedArrayWithFormattedDate;
+    }
+}

+ 64 - 0
tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php

@@ -23,8 +23,10 @@ use JMS\Serializer\DeserializationContext;
 use JMS\Serializer\GraphNavigator;
 use JMS\Serializer\Handler\PhpCollectionHandler;
 use JMS\Serializer\SerializationContext;
+use JMS\Serializer\Tests\Fixtures\DateTimeArraysObject;
 use JMS\Serializer\Tests\Fixtures\Discriminator\Car;
 use JMS\Serializer\Tests\Fixtures\InlineChildEmpty;
+use JMS\Serializer\Tests\Fixtures\NamedDateTimeArraysObject;
 use JMS\Serializer\Tests\Fixtures\Tree;
 use PhpCollection\Sequence;
 use Symfony\Component\Form\FormFactoryBuilder;
@@ -254,6 +256,68 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+
+    public function testDateTimeArrays()
+    {
+        $data = array(
+            new \DateTime('2047-01-01 12:47:47', new \DateTimeZone('UTC')),
+            new \DateTime('2013-12-05 00:00:00', new \DateTimeZone('UTC'))
+        );
+
+        $object = new DateTimeArraysObject($data, $data);
+        $serializedObject = $this->serialize( $object );
+
+        $this->assertEquals($this->getContent('array_datetimes_object'), $serializedObject);
+
+        if ($this->hasDeserializer()) {
+            /** @var DateTimeArraysObject $deserializedObject */
+            $deserializedObject = $this->deserialize($this->getContent('array_datetimes_object'), 'Jms\Serializer\Tests\Fixtures\DateTimeArraysObject');
+
+            /** deserialized object has a default timezone set depending on user's timezone settings. That's why we manually set the UTC timezone on the DateTime objects. */
+            foreach ($deserializedObject->getArrayWithDefaultDateTime() as $dateTime) {
+                $dateTime->setTimezone(new \DateTimeZone('UTC'));
+            }
+
+            foreach ($deserializedObject->getArrayWithFormattedDateTime() as $dateTime) {
+                $dateTime->setTimezone(new \DateTimeZone('UTC'));
+            }
+
+            $this->assertEquals($object, $deserializedObject);
+        }
+    }
+
+    public function testNamedDateTimeArrays()
+    {
+        $data = array(
+            new \DateTime('2047-01-01 12:47:47', new \DateTimeZone('UTC')),
+            new \DateTime('2013-12-05 00:00:00', new \DateTimeZone('UTC'))
+        );
+
+        $object = new NamedDateTimeArraysObject(array('testdate1' => $data[0], 'testdate2' => $data[1]));
+        $serializedObject = $this->serialize( $object );
+
+        $this->assertEquals($this->getContent('array_named_datetimes_object'), $serializedObject);
+
+        if ($this->hasDeserializer()) {
+
+            // skip XML deserialization
+            if ($this->getFormat() === 'xml') {
+                return;
+            }
+
+            /** @var NamedDateTimeArraysObject $deserializedObject */
+            $deserializedObject = $this->deserialize($this->getContent('array_named_datetimes_object'), 'Jms\Serializer\Tests\Fixtures\NamedDateTimeArraysObject');
+
+            /** deserialized object has a default timezone set depending on user's timezone settings. That's why we manually set the UTC timezone on the DateTime objects. */
+            foreach ($deserializedObject->getNamedArrayWithFormattedDate() as $dateTime) {
+                $dateTime->setTimezone(new \DateTimeZone('UTC'));
+            }
+
+            $this->assertEquals($object, $deserializedObject);
+        }
+    }
+
+
     public function testArrayMixed()
     {
         $this->assertEquals($this->getContent('array_mixed'), $this->serialize(array('foo', 1, true, new SimpleObject('foo', 'bar'), array(1, 3, true))));

+ 2 - 0
tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php

@@ -49,6 +49,8 @@ class JsonSerializationTest extends BaseSerializationTest
             $outputs['array_floats'] = '[1.34,3,6.42]';
             $outputs['array_objects'] = '[{"foo":"foo","moo":"bar","camel_case":"boo"},{"foo":"baz","moo":"boo","camel_case":"boo"}]';
             $outputs['array_mixed'] = '["foo",1,true,{"foo":"foo","moo":"bar","camel_case":"boo"},[1,3,true]]';
+            $outputs['array_datetimes_object'] = '{"array_with_default_date_time":["2047-01-01T12:47:47+0000","2013-12-05T00:00:00+0000"],"array_with_formatted_date_time":["01.01.2047 12:47:47","05.12.2013 00:00:00"]}';
+            $outputs['array_named_datetimes_object'] = '{"named_array_with_formatted_date":{"testdate1":"01.01.2047 12:47:47","testdate2":"05.12.2013 00:00:00"}}';
             $outputs['blog_post'] = '{"id":"what_a_nice_id","title":"This is a nice title.","created_at":"2011-07-30T00:00:00+0000","is_published":false,"etag":"1edf9bf60a32d89afbb85b2be849e3ceed5f5b10","comments":[{"author":{"full_name":"Foo Bar"},"text":"foo"}],"comments2":[{"author":{"full_name":"Foo Bar"},"text":"foo"}],"metadata":{"foo":"bar"},"author":{"full_name":"Foo Bar"},"publisher":{"pub_name":"Bar Foo"}}';
             $outputs['blog_post_unauthored'] = '{"id":"what_a_nice_id","title":"This is a nice title.","created_at":"2011-07-30T00:00:00+0000","is_published":false,"etag":"1edf9bf60a32d89afbb85b2be849e3ceed5f5b10","comments":[],"comments2":[],"metadata":{"foo":"bar"},"author":null,"publisher":null}';
             $outputs['price'] = '{"price":3}';

+ 11 - 0
tests/JMS/Serializer/Tests/Serializer/xml/array_datetimes_object.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <array_with_default_date_time>
+    <entry><![CDATA[2047-01-01T12:47:47+0000]]></entry>
+    <entry><![CDATA[2013-12-05T00:00:00+0000]]></entry>
+  </array_with_default_date_time>
+  <array_with_formatted_date_time>
+    <entry><![CDATA[01.01.2047 12:47:47]]></entry>
+    <entry><![CDATA[05.12.2013 00:00:00]]></entry>
+  </array_with_formatted_date_time>
+</result>

+ 7 - 0
tests/JMS/Serializer/Tests/Serializer/xml/array_named_datetimes_object.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <named_array_with_formatted_date>
+    <testdate1><![CDATA[01.01.2047 12:47:47]]></testdate1>
+    <testdate2><![CDATA[05.12.2013 00:00:00]]></testdate2>
+  </named_array_with_formatted_date>
+</result>

+ 6 - 0
tests/JMS/Serializer/Tests/Serializer/yml/array_datetimes_object.yml

@@ -0,0 +1,6 @@
+array_with_default_date_time:
+    - '2047-01-01T12:47:47+0000'
+    - '2013-12-05T00:00:00+0000'
+array_with_formatted_date_time:
+    - '01.01.2047 12:47:47'
+    - '05.12.2013 00:00:00'

+ 3 - 0
tests/JMS/Serializer/Tests/Serializer/yml/array_named_datetimes_object.yml

@@ -0,0 +1,3 @@
+named_array_with_formatted_date:
+    testdate1: '01.01.2047 12:47:47'
+    testdate2: '05.12.2013 00:00:00'