Skip to content

Commit 1767acf

Browse files
jarstelfoxclaude
andcommitted
fix: Serialize native PHP enums with their name and value instead of opaque 'Object' string
Enums were caught by the generic `is_object` branch in `serializeRecursively()`, causing them to render as `Object ClassName` when `serializeAllObjects` was enabled. This adds an early-return for `UnitEnum` before the object block and enhances the output to include the backing value for `BackedEnum` instances. Fixes #2037 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d94ee1b commit 1767acf

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

src/Serializer/AbstractSerializer.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ protected function serializeRecursively($value, int $_depth = 0)
116116
return $serializedArray;
117117
}
118118

119+
if ($value instanceof \UnitEnum) {
120+
return $this->serializeValue($value);
121+
}
122+
119123
if (\is_object($value)) {
120124
$classSerializers = $this->resolveClassSerializers($value);
121125

@@ -247,8 +251,13 @@ protected function serializeValue($value)
247251

248252
if ($value instanceof \UnitEnum) {
249253
$reflection = new \ReflectionObject($value);
254+
$enumValue = $reflection->getName() . '::' . $value->name;
255+
256+
if ($value instanceof \BackedEnum) {
257+
return 'Enum ' . $enumValue . '(' . $value->value . ')';
258+
}
250259

251-
return 'Enum ' . $reflection->getName() . '::' . $value->name;
260+
return 'Enum ' . $enumValue;
252261
}
253262

254263
if (\is_object($value)) {

tests/Serializer/AbstractSerializerTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,54 @@ public function testEnumsAreNames(): void
6666
$this->assertSame('Enum Sentry\Tests\Serializer\SerializerTestEnum::CASE_NAME', $result);
6767
}
6868

69+
/**
70+
* @requires PHP >= 8.1
71+
*/
72+
public function testBackedEnumsIncludeValue(): void
73+
{
74+
$serializer = $this->createSerializer();
75+
$input = SerializerTestBackedEnum::CASE_NAME;
76+
$result = $this->invokeSerialization($serializer, $input);
77+
78+
$this->assertSame('Enum Sentry\Tests\Serializer\SerializerTestBackedEnum::CASE_NAME(case_value)', $result);
79+
}
80+
81+
/**
82+
* @requires PHP >= 8.1
83+
* @dataProvider serializeAllObjectsDataProvider
84+
*/
85+
public function testEnumsAreNotSerializedAsObjects(bool $serializeAllObjects): void
86+
{
87+
$serializer = $this->createSerializer();
88+
89+
if ($serializeAllObjects) {
90+
$serializer->setSerializeAllObjects(true);
91+
}
92+
93+
$input = SerializerTestEnum::CASE_NAME;
94+
$result = $this->invokeSerialization($serializer, $input);
95+
96+
$this->assertSame('Enum Sentry\Tests\Serializer\SerializerTestEnum::CASE_NAME', $result);
97+
}
98+
99+
/**
100+
* @requires PHP >= 8.1
101+
* @dataProvider serializeAllObjectsDataProvider
102+
*/
103+
public function testBackedEnumsAreNotSerializedAsObjects(bool $serializeAllObjects): void
104+
{
105+
$serializer = $this->createSerializer();
106+
107+
if ($serializeAllObjects) {
108+
$serializer->setSerializeAllObjects(true);
109+
}
110+
111+
$input = SerializerTestBackedEnum::CASE_NAME;
112+
$result = $this->invokeSerialization($serializer, $input);
113+
114+
$this->assertSame('Enum Sentry\Tests\Serializer\SerializerTestBackedEnum::CASE_NAME(case_value)', $result);
115+
}
116+
69117
public static function objectsWithIdPropertyDataProvider(): array
70118
{
71119
return [
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Tests\Serializer;
6+
7+
enum SerializerTestBackedEnum: string
8+
{
9+
case CASE_NAME = 'case_value';
10+
}

0 commit comments

Comments
 (0)