Skip to content

Commit

Permalink
add documentation and metadata drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
goetas committed Aug 18, 2024
1 parent beba384 commit 568f439
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 0 deletions.
7 changes: 7 additions & 0 deletions doc/reference/xml_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ XML Reference
<value>foo</value>
<value>bar</value>
</groups>
<union-discriminator field="foo">
<map>
<class key="a">SomeClassFQCN1</class>
<class key="b">SomeClassFQCN2</class>
<class key="c">SomeClassFQCN3</class>
</map>
</union-discriminator>
</property>
<callback-method name="foo" type="pre-serialize" />
<callback-method name="bar" type="post-serialize" />
Expand Down
6 changes: 6 additions & 0 deletions doc/reference/yml_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ YAML Reference
cdata: false
namespace: http://www.w3.org/2005/Atom
max_depth: 2
union_discriminator:
filed: foo
map:
a: SomeClassFQCN1
b: SomeClassFQCN2
c: SomeClassFQCN3
callback_methods:
pre_serialize: [foo, bar]
Expand Down
15 changes: 15 additions & 0 deletions src/Metadata/Driver/XmlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,21 @@ protected function loadMetadataFromFile(\ReflectionClass $class, string $path):
$pMetadata->readOnly = $pMetadata->readOnly || $readOnlyClass;
}

if (isset($pElem->{'union-discriminator'})) {
$colConfig = $pElem->{'union-discriminator'};

$map = [];
foreach ($pElem->xpath('./union-discriminator/map/class') as $entry) {
$map[(string) $entry->attributes()->key] = (string) $entry;
}

$pMetadata->setUnionDiscriminator((string) $colConfig->attributes()->field, $map);
$pMetadata->setType([
'name' => 'union',
'params' => [null, (string) $colConfig->attributes()->field, $map],
]);
}

$getter = $pElem->attributes()->{'accessor-getter'};
$setter = $pElem->attributes()->{'accessor-setter'};
$pMetadata->setAccessor(
Expand Down
8 changes: 8 additions & 0 deletions src/Metadata/Driver/YamlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,14 @@ protected function loadMetadataFromFile(ReflectionClass $class, string $file): ?
if (isset($pConfig['max_depth'])) {
$pMetadata->maxDepth = (int) $pConfig['max_depth'];
}

if (isset($pConfig['union_discriminator'])) {
$pMetadata->setUnionDiscriminator($pConfig['union_discriminator']['field'], $pConfig['union_discriminator']['map']);
$pMetadata->setType([
'name' => 'union',
'params' => [null, $pConfig['union_discriminator']['field'], $pConfig['union_discriminator']['map']],
]);
}
}

if (!$pMetadata->serializedName) {
Expand Down
6 changes: 6 additions & 0 deletions tests/Fixtures/TypedProperties/ComplexDiscriminatedUnion.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

class ComplexDiscriminatedUnion
{
/**
* @UnionDiscriminator(
* field = "objectType",
* map = {"author": "JMS\Serializer\Tests\Fixtures\DiscriminatedAuthor", "comment": "JMS\Serializer\Tests\Fixtures\DiscriminatedComment"}
* )"
*/
#[UnionDiscriminator(field: 'objectType', map: ['author' => 'JMS\Serializer\Tests\Fixtures\DiscriminatedAuthor', 'comment' => 'JMS\Serializer\Tests\Fixtures\DiscriminatedComment'])]
private DiscriminatedAuthor|DiscriminatedComment $data;

Expand Down
12 changes: 12 additions & 0 deletions tests/Metadata/Driver/BaseDriverTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use JMS\Serializer\Tests\Fixtures\ObjectWithVirtualPropertiesAndExcludeAll;
use JMS\Serializer\Tests\Fixtures\ParentSkipWithEmptyChild;
use JMS\Serializer\Tests\Fixtures\Person;
use JMS\Serializer\Tests\Fixtures\TypedProperties\ComplexDiscriminatedUnion;
use Metadata\Driver\DriverInterface;
use Metadata\MethodMetadata;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -133,6 +134,17 @@ public function testXMLListAbsentNode()
self::assertFalse($m->propertyMetadata['present']->xmlCollectionSkipWhenEmpty);
}

public function testUnionDiscriminator()
{
$m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass(ComplexDiscriminatedUnion::class));
\assert($m instanceof ClassMetadata);

$p = $m->propertyMetadata['data'];
assert($p instanceof PropertyMetadata);
self::assertEquals('objectType', $p->unionDiscriminatorField);
self::assertEquals(['author' => 'JMS\Serializer\Tests\Fixtures\DiscriminatedAuthor', 'comment' => 'JMS\Serializer\Tests\Fixtures\DiscriminatedComment'], $p->unionDiscriminatorMap);
}

public function testVirtualProperty()
{
$m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties'));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<class name="JMS\Serializer\Tests\Fixtures\TypedProperties\ComplexDiscriminatedUnion">
<property name="data">
<union-discriminator field="objectType">
<map>
<class key="author">JMS\Serializer\Tests\Fixtures\DiscriminatedAuthor</class>
<class key="comment">JMS\Serializer\Tests\Fixtures\DiscriminatedComment</class>
</map>
</union-discriminator>
</property>
</class>
</serializer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
JMS\Serializer\Tests\Fixtures\TypedProperties\ComplexDiscriminatedUnion:
properties:
data:
union_discriminator:
field: objectType
map:
author: 'JMS\Serializer\Tests\Fixtures\DiscriminatedAuthor'
comment: 'JMS\Serializer\Tests\Fixtures\DiscriminatedComment'
29 changes: 29 additions & 0 deletions tests/Serializer/JsonSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\Exception\NonVisitableTypeException;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Metadata\Driver\TypedPropertiesDriver;
Expand Down Expand Up @@ -154,6 +155,8 @@ protected static function getContent($key)
$outputs['data_comment'] = '{"data":{"author":{"full_name":"foo"},"text":"bar"}}';
$outputs['data_discriminated_author'] = '{"data":{"full_name":"foo","objectType":"author"}}';
$outputs['data_discriminated_comment'] = '{"data":{"author":{"full_name":"foo"},"text":"bar","objectType":"comment"}}';
$outputs['data_discriminated_comment_wrong_discriminator'] = '{"data":{"author":{"full_name":"foo"},"text":"bar","objectType":"comment_wrong"}}';
$outputs['data_discriminated_comment_missing_discriminator'] = '{"data":{"author":{"full_name":"foo"},"text":"bar"}}';
$outputs['uid'] = '"66b3177c-e03b-4a22-9dee-ddd7d37a04d5"';
$outputs['object_with_enums'] = '{"ordinary":"Clubs","backed_value":"C","backed_without_param":"C","ordinary_array":["Clubs","Spades"],"backed_array":["C","H"],"backed_array_without_param":["C","H"],"ordinary_auto_detect":"Clubs","backed_auto_detect":"C","backed_int_auto_detect":3,"backed_int":3,"backed_name":"C","backed_int_forced_str":3}';
$outputs['object_with_autodetect_enums'] = '{"ordinary_array_auto_detect":["Clubs","Spades"],"backed_array_auto_detect":["C","H"],"mixed_array_auto_detect":["Clubs","H"]}';
Expand Down Expand Up @@ -493,6 +496,32 @@ public function testDeserializingComplexDiscriminatedUnionProperties()
self::assertEquals($commentUnion, $this->deserialize(static::getContent('data_discriminated_comment'), ComplexDiscriminatedUnion::class));
}

public function testDeserializingComplexDiscriminatedUnionPropertiesFailsWhenDiscriminatorNotInMap()
{
if (PHP_VERSION_ID < 80000) {
$this->markTestSkipped(sprintf('%s requires PHP 8.0', TypedPropertiesDriver::class));

return;
}

$this->expectException(NonVisitableTypeException::class);
$this->expectExceptionMessage('Union Discriminator Map does not contain key "comment_wrong"');
$this->deserialize(static::getContent('data_discriminated_comment_wrong_discriminator'), ComplexDiscriminatedUnion::class);
}

public function testDeserializingComplexDiscriminatedUnionPropertiesFailsWhenDiscriminatorIsMissing()
{
if (PHP_VERSION_ID < 80000) {
$this->markTestSkipped(sprintf('%s requires PHP 8.0', TypedPropertiesDriver::class));

return;
}

$this->expectException(NonVisitableTypeException::class);
$this->expectExceptionMessage('Union Discriminator Field "objectType" not found in data');
$this->deserialize(static::getContent('data_discriminated_comment_missing_discriminator'), ComplexDiscriminatedUnion::class);
}

public function testSerializeingComplexDiscriminatedUnionProperties()
{
if (PHP_VERSION_ID < 80000) {
Expand Down

0 comments on commit 568f439

Please sign in to comment.