8000 [Serializer][PropertyAccess] DX friendly Exception - PropertyAccess always camelizes property names · Issue #23656 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Serializer][PropertyAccess] DX friendly Exception - PropertyAccess always camelizes property names #23656

Closed
@DavidBadura

Description

@DavidBadura
Q A
Bug report? yes?
Feature request? yes?
BC Break report? no
RFC? no
Symfony version tbd

My colleagues and I have come across the following problem quite often:

/*
 * This works like expected \o/
 */
$this->get('serializer')->deserialize('{"updatedAt": "2017-06-15"}', User::class, 'json');

/*
 * Get a weird exception:
 * Expected argument of type "DateTime", "string" given
 */
$this->get('serializer')->deserialize('{"updated_at": "2017-06-15"}', User::class, 'json');

This exception is really weird because it says it can find the setter but not a type. It seems to be a PropertyInfo or Normalizer problem. So after getting this exception you naturally check the framework configuration, or if there is a missing normalizer or a missing property info etc. But the real cause is the PropertyAccessor, because it always camelizes the property name.

This is what happens in the background:

  • PropertyInfo doesn't camelize the key 'updated_at', so it can't find the property 'updatedAt' or setter 'setUpdatedAt'.
  • Because of that it doesn't get the correct type to convert the string to a DateTime object.
  • PropertyAccess always camelizes the key and it tries to set the string value. But it doesn't work because of type mismatch and you get an invalid argument exception.

I have created a new Symfony Standard Edition project with minimal changes to reproduce this issue: https://github.com/DavidBadura/symfony-serializer


So what can we do here?

  1. add a new PropertyAccess option

PropertyAccess gets a flag "don't camelize" (tbd), so you can create a special PropertyAccessor for the Serializer component. So the PropertyAccessor can throw an property or setter not found exception.

private function camelize($string)
{
    if ($this->doNotCamelize) { // tbd
       return ucfirst($string);
    }

    return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
}

(https://github.com/symfony/symfony/blob/master/src/Symfony/Component/PropertyAccess/PropertyAccessor.php#L732)

  1. ObjectNormalizer checks property name

ObjectNormalizer checks if the property with this name exists otherwise it throws an exception. But
it won't be as performant as before and i think it shouldn't be its scope.


The goal should be to throw a DX friendly exception. I can create a merge request if we decide what we want to do :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    DXDX = Developer eXperience (anything that improves the experience of using Symfony)FeaturePropertyAccessSerializerStalled

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0