Skip to content

Commit

Permalink
Merge pull request #749 from schmittjoh/std-class-serialization
Browse files Browse the repository at this point in the history
Added stdClass serialization handler
  • Loading branch information
goetas authored Apr 21, 2017
2 parents 068c5a5 + ac92445 commit 89419d1
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
16 changes: 16 additions & 0 deletions doc/cookbook/stdclass.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
stdClass
========

The serializer offers support for serializing ``stdClass`` objects, however the use of
``stdClass`` objects is discouraged.

The current implementation serializes all the properties of a ``stdClass`` object in
the order they appear.

There are may know limitations wen dealing with ``stdClass`` objects,
more in detail, is not possible to:

- change serialization order of properties
- apply per-property exclusion policies
- specify any extra serialization information for properties that are part of the ``stdClass`` object, as serialization name, type, xml structure and so on
- deserialize data into ``stdClass`` objects
60 changes: 60 additions & 0 deletions src/JMS/Serializer/Handler/StdClassHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?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\Handler;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
use JMS\Serializer\VisitorInterface;

/**
* @author Asmir Mustafic <[email protected]>
*/
class StdClassHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
$methods = array();
$formats = array('json', 'xml', 'yml');

foreach ($formats as $format) {
$methods[] = array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'type' => 'stdClass',
'format' => $format,
'method' => 'serializeStdClass',
);
}

return $methods;
}

public function serializeStdClass(VisitorInterface $visitor, \stdClass $stdClass, array $type, Context $context)
{
$classMetadata = $context->getMetadataFactory()->getMetadataForClass('stdClass');
$visitor->startVisitingObject($classMetadata, $stdClass, array('name' => 'stdClass'), $context);

foreach ((array)$stdClass as $name => $value) {
$metadata = new StaticPropertyMetadata('stdClass', $name, $value);
$visitor->visitProperty($metadata, $value, $context);
}

return $visitor->endVisitingObject($classMetadata, $stdClass, array('name' => 'stdClass'), $context);
}
}
2 changes: 2 additions & 0 deletions src/JMS/Serializer/SerializerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use JMS\Serializer\Handler\PhpCollectionHandler;
use JMS\Serializer\Handler\PropelCollectionHandler;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Handler\StdClassHandler;
use Metadata\Driver\DriverInterface;
use Metadata\MetadataFactory;
use JMS\Serializer\Metadata\Driver\AnnotationDriver;
Expand Down Expand Up @@ -162,6 +163,7 @@ public function addDefaultHandlers()
{
$this->handlersConfigured = true;
$this->handlerRegistry->registerSubscribingHandler(new DateHandler());
$this->handlerRegistry->registerSubscribingHandler(new StdClassHandler());
$this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler());
$this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler());
$this->handlerRegistry->registerSubscribingHandler(new PropelCollectionHandler());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use JMS\Serializer\Expression\ExpressionEvaluator;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\PhpCollectionHandler;
use JMS\Serializer\Handler\StdClassHandler;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\Tests\Fixtures\AuthorExpressionAccess;
use JMS\Serializer\Tests\Fixtures\DateTimeArraysObject;
Expand Down Expand Up @@ -1328,6 +1329,7 @@ protected function setUp()

$this->handlerRegistry = new HandlerRegistry();
$this->handlerRegistry->registerSubscribingHandler(new ConstraintViolationHandler());
$this->handlerRegistry->registerSubscribingHandler(new StdClassHandler());
$this->handlerRegistry->registerSubscribingHandler(new DateHandler());
$this->handlerRegistry->registerSubscribingHandler(new FormErrorHandler(new IdentityTranslator(new MessageSelector())));
$this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler());
Expand Down
41 changes: 40 additions & 1 deletion tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Tests\Fixtures\Tag;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Tests\Fixtures\Author;
use JMS\Serializer\Tests\Fixtures\AuthorList;
Expand Down Expand Up @@ -299,7 +300,7 @@ public function getTypeHintedArrays()
[[1, 2], '[1,2]', null],
[['a', 'b'], '["a","b"]', null],
[['a' => 'a', 'b' => 'b'], '{"a":"a","b":"b"}', null],

[[], '[]', null],
[[], '[]', SerializationContext::create()->setInitialType('array')],
[[], '[]', SerializationContext::create()->setInitialType('array<integer>')],
Expand Down Expand Up @@ -336,6 +337,44 @@ public function testTypeHintedArraySerialization(array $array, $expected, $conte
$this->assertEquals($expected, $this->serialize($array, $context));
}

public function getTypeHintedArraysAndStdClass()
{
$c1 = new \stdClass();
$c2 = new \stdClass();
$c2->foo = 'bar';

$tag = new Tag("tag");

$c3 = new \stdClass();
$c3->foo = $tag;

return [

[[$c2], '[{"foo":"bar"}]', SerializationContext::create()->setInitialType('array<stdClass>')],

[[$tag], '[{"name":"tag"}]', SerializationContext::create()->setInitialType('array<JMS\Serializer\Tests\Fixtures\Tag>')],

[[$c1], '{"0":{}}', SerializationContext::create()->setInitialType('array<integer,stdClass>')],
[[$c2], '{"0":{"foo":"bar"}}', SerializationContext::create()->setInitialType('array<integer,stdClass>')],

[[$c3], '{"0":{"foo":{"name":"tag"}}}', SerializationContext::create()->setInitialType('array<integer,stdClass>')],
[[$c3], '[{"foo":{"name":"tag"}}]', SerializationContext::create()->setInitialType('array<stdClass>')],

[[$tag], '{"0":{"name":"tag"}}', SerializationContext::create()->setInitialType('array<integer,JMS\Serializer\Tests\Fixtures\Tag>')],
];
}

/**
* @dataProvider getTypeHintedArraysAndStdClass
* @param array $array
* @param string $expected
* @param SerializationContext|null $context
*/
public function testTypeHintedArrayAndStdClassSerialization(array $array, $expected, $context = null)
{
$this->assertEquals($expected, $this->serialize($array, $context));
}

protected function getFormat()
{
return 'json';
Expand Down

0 comments on commit 89419d1

Please sign in to comment.