Skip to content

Instantly share code, notes, and snippets.

@skobkin
Last active August 27, 2024 16:47
Show Gist options
  • Save skobkin/41d2a0f15375344e2858b86d25f62e39 to your computer and use it in GitHub Desktop.
Save skobkin/41d2a0f15375344e2858b86d25f62e39 to your computer and use it in GitHub Desktop.
ReflectionExtractor somewhat unexpected type detection behavior

Using Symfony Serializer with Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor will cause the type of $url property to be detected incorrectly.

$serializer->deserialize(SomeResponse::class, '{"url": "http://test"}');

We'll get an exception with an error like this:

The type of the "url" attribute for class "SomeResponse" must be one of "bool" ("string" given).

That's because ReflectionExtractor does this:

public function getTypes(string $class, string $property, array $context = []): ?array
{
    if ($fromMutator = $this->extractFromMutator($class, $property)) { // skipped, but will also cause same problem if mutator is present
        return $fromMutator;
    }
    if ($fromAccessor = $this->extractFromAccessor($class, $property)) { // here we go
        return $fromAccessor; // data suggesting 'bool' returned before extracting from constructor
    }
    if (
        ($context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction)
        && $fromConstructor = $this->extractFromConstructor($class, $property)
    ) {
        return $fromConstructor;
    }
    if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) {
        return $fromPropertyDeclaration;
    }
    return null;
}

That's a bit unexpected, I guess 🤷

Already reported: symfony/symfony#57719

<?php
class SomeResponse
{
public function __construct(
#[SerializedName('url')]
public readonly ?string $url,
) {
}
public function hasUrl(): bool
{
return !empty($this->url);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment