Skip to content

Commit

Permalink
Add workaround example
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoweiland committed Jul 1, 2020
1 parent 84da690 commit 82a5953
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 1 deletion.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ Install composer dependencies
composer install
```

And run test with phpunit
Failing test using `@Type("array<Hashid,string>")`

```
vendor/bin/phpunit test/SerializerTest.php
```

Working test with workaround using `@Type("KeyValueArray<Hashid,string>")`

```
vendor/bin/phpunit test/WorkaroundTest.php
```
64 changes: 64 additions & 0 deletions test/KeyValueArraySubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Test;

use Exception;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use function count;

class KeyValueArraySubscriber implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return [
[
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => 'KeyValueArray',
'method' => 'handle',
],
[
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'format' => 'json',
'type' => 'KeyValueArray',
'method' => 'handle',
],
];
}

/**
* @param mixed $visitor
* @param mixed $map
* @param array $type
* @param Context $context
* @return array<mixed,mixed>
*/
public function handle($visitor, $map, array $type, Context $context): array
{
if (!is_iterable($map)) {
return [];
}

if (count($type['params']) !== 2) {
throw new Exception('KeyValueArray requires key and value types');
}

$keyType = $type['params'][0];
$valueType = $type['params'][1];
$navigator = $context->getNavigator();
$output = [];

foreach ($map as $key => $value) {
$outputKey = $navigator->accept($key, $keyType);
$outputValue = $navigator->accept($value, $valueType);
$output[$outputKey] = $outputValue;
}

return $output;
}
}

21 changes: 21 additions & 0 deletions test/ReportWithWorkaround.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Test;

use JMS\Serializer\Annotation as JMS;

class ReportWithWorkaround
{
/**
* @var array<int,string>
* @JMS\Type("KeyValueArray<Hashid,string>")
*/
public array $items = [];

public function addItem(int $id, string $value): void
{
$this->items[$id] = $value;
}
}
59 changes: 59 additions & 0 deletions test/WorkaroundTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Test;

use Hashids\Hashids;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\SerializerInterface;
use PHPUnit\Framework\TestCase;

class WorkaroundTest extends TestCase
{
private const JSON = '{"items":{"Pe9xdL":"99.80","nelx6e":"154.00"}}';

private SerializerInterface $serializer;

protected function setUp(): void
{
$this->serializer = SerializerBuilder::create()
->addDefaultHandlers()
->configureHandlers(function(HandlerRegistry $registry) {
$hashids = new Hashids('', 6);
$hashidsHandler = new HashidsSubscriber($hashids);
$keyValueHandler = new KeyValueArraySubscriber($hashids);

$registry->registerSubscribingHandler($hashidsHandler);
$registry->registerSubscribingHandler($keyValueHandler);
})
->build();
}

public function testDeserialize(): void
{
$deserialized = $this->serializer->deserialize(self::JSON, ReportWithWorkaround::class, 'json');

$this->assertInstanceOf(ReportWithWorkaround::class, $deserialized);
$this->assertCount(2, $deserialized->items);

$this->assertArrayHasKey(42, $deserialized->items);
$this->assertEquals('99.80', $deserialized->items[42]);

$this->assertArrayHasKey(191, $deserialized->items);
$this->assertEquals('154.00', $deserialized->items[191]);
}

public function testSerialize(): void
{
$report = new ReportWithWorkaround();
$report->addItem(42, '99.80');
$report->addItem(191, '154.00');

$serialized = $this->serializer->serialize($report, 'json');

// This works
$this->assertJsonStringEqualsJsonString(self::JSON, $serialized);
}
}

0 comments on commit 82a5953

Please sign in to comment.