Skip to content

Commit 9023cf7

Browse files
committed
Fix failing enum mapping for backed PHP enums
1 parent 8c64d8d commit 9023cf7

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

src/JsonMapper.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,20 @@ public function map($json, $object)
296296
} else if (is_array($jvalue) && $this->hasVariadicArrayType($accessor)) {
297297
$array = array();
298298
$subtype = $type;
299-
} else {
300-
if (is_a($type, 'ArrayAccess', true)
301-
&& is_a($type, 'Traversable', true)
302-
) {
303-
$array = $this->createInstance($type, false, $jvalue);
299+
} else if (is_a($type, 'ArrayAccess', true)
300+
&& is_a($type, 'Traversable', true)
301+
) {
302+
$array = $this->createInstance($type, false, $jvalue);
303+
} else if (PHP_VERSION_ID >= 80100 && enum_exists($type)) {
304+
$evalue = $type::tryFrom($jvalue);
305+
if ($evalue === null) {
306+
throw new JsonMapper_Exception(
307+
'Enum value "' . $jvalue . '" does not belong to '
308+
. $type . ' enumerator class'
309+
);
304310
}
311+
$this->setProperty($object, $accessor, $evalue);
312+
continue;
305313
}
306314

307315
if ($array !== null) {

tests/Enums_PHP81_Test.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,45 @@ public function testEnumMapping()
3232
$this->assertSame(\Enums\StringBackedEnum::FOO, $sn->stringBackedEnum);
3333
$this->assertSame(\Enums\IntBackedEnum::BAR, $sn->intBackedEnum);
3434
}
35+
36+
/**
37+
* Test that string values are correctly mapped to backed enum properties.
38+
*/
39+
public function testBackedEnumPropertyIsMappedFromString(): void
40+
{
41+
$json = (object) [
42+
'stringBackedEnum' => 'foo',
43+
'intBackedEnum' => 2,
44+
];
45+
46+
$mapper = new \JsonMapper();
47+
$target = new \Enums\ObjectWithEnum();
48+
49+
$mapped = $mapper->map($json, $target);
50+
51+
$this->assertSame(
52+
\Enums\StringBackedEnum::FOO,
53+
$mapped->stringBackedEnum,
54+
'Expected JSON scalar to be converted to the corresponding backed enum case'
55+
);
56+
}
57+
58+
/**
59+
* Test that mapping invalid string values to backed enum properties throws an exception.
60+
*/
61+
public function testBackedEnumPropertyWithInvalidStringThrowsJsonMapperException(): void
62+
{
63+
$json = (object) [
64+
'stringBackedEnum' => 'not-a-valid-enum-value',
65+
'intBackedEnum' => 'not-a-valid-enum-value',
66+
];
67+
68+
$mapper = new \JsonMapper();
69+
$target = new \Enums\ObjectWithEnum();
70+
71+
$this->expectException(\JsonMapper_Exception::class);
72+
$this->expectExceptionMessage('Enum value "not-a-valid-enum-value" does not belong to');
73+
74+
$mapper->map($json, $target);
75+
}
3576
}

0 commit comments

Comments
 (0)