Skip to content

Commit

Permalink
Add support for forced enum name serialization using JMS
Browse files Browse the repository at this point in the history
  • Loading branch information
bobvandevijver committed Oct 31, 2024
1 parent 1e283ef commit f90f083
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/ModelDescriber/EnumModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@

class EnumModelDescriber implements ModelDescriberInterface
{
public const FORCE_NAMES = '_nelmio_enum_force_names';

public function describe(Model $model, Schema $schema)
{
$enumClass = $model->getType()->getClassName();
$forceName = isset($model->getSerializationContext()[self::FORCE_NAMES]) && true === $model->getSerializationContext()[self::FORCE_NAMES];

$enums = [];
foreach ($enumClass::cases() as $enumCase) {
$enums[] = $enumCase->value;
$enums[] = $forceName ? $enumCase->name : $enumCase->value;
}

$reflectionEnum = new \ReflectionEnum($enumClass);
if ($reflectionEnum->isBacked() && 'int' === $reflectionEnum->getBackingType()->getName()) {
if (!$forceName && $reflectionEnum->isBacked() && 'int' === $reflectionEnum->getBackingType()->getName()) {
$schema->type = 'integer';
} else {
$schema->type = 'string';
Expand Down
9 changes: 9 additions & 0 deletions src/ModelDescriber/JMSModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,15 @@ public function describeItem(array $type, OA\Schema $property, Context $context,
if (is_string($typeParam) && enum_exists($typeParam)) {
$type['name'] = $typeParam;
}

if (isset($type['params'][1])) {
if ('value' !== $type['params'][1] && is_a($type['name'], \BackedEnum::class, true)) {
// In case of a backed enum, it is possible to serialize it using its names instead of values
// Set a specific serialization context property to enforce a new model, as options cannot be used to force a new model
// See https://github.com/schmittjoh/serializer/blob/5a5a03a71a28a480189c5a0ca95893c19f1d120c/src/Handler/EnumHandler.php#L47
$serializationContext[EnumModelDescriber::FORCE_NAMES] = true;
}
}
}

$groups = $this->computeGroups($context, $type);
Expand Down
8 changes: 8 additions & 0 deletions tests/Functional/Entity/JMSEnum81.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ class JMSEnum81
#[Serializer\Type('array<enum<'.ArticleType81::class.", 'value'>>")]
#[Serializer\Expose]
public $enumValues;

#[Serializer\Type('enum<'.ArticleType81::class.", 'name'>")]
#[Serializer\Expose]
public $enumName;

#[Serializer\Type('array<enum<'.ArticleType81::class.", 'name'>>")]
#[Serializer\Expose]
public $enumNames;
}
18 changes: 18 additions & 0 deletions tests/Functional/JMSFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,15 @@ public function testEnumSupport(): void
return;
}

self::assertEquals([
'schema' => 'ArticleType812',
'type' => 'string',
'enum' => [
'DRAFT',
'FINAL'
]
], json_decode($this->getModel('ArticleType812')->toJson(), true));

self::assertEquals([
'schema' => 'JMSEnum81',
'type' => 'object',
Expand All @@ -398,6 +407,15 @@ public function testEnumSupport(): void
'$ref' => '#/components/schemas/ArticleType81'
]
],
'enum_name' => [
'$ref' => '#/components/schemas/ArticleType812'
],
'enum_names' => [
'type' => 'array',
'items' => [
'$ref' => '#/components/schemas/ArticleType812'
]
],
]
], json_decode($this->getModel('JMSEnum81')->toJson(), true));
}
Expand Down

0 comments on commit f90f083

Please sign in to comment.