Fosuserbundle: Deserialize json to user object "You must define a type"

Created on 14 Apr 2013  路  14Comments  路  Source: FriendsOfSymfony/FOSUserBundle

$this->get('request')->getContent()

returns

{"id":2,"username":"[email protected]","username_canonical":"[email protected]", ... }

Deserialization:

$data = $serializer->deserialize($this->get('request')->getContent(), 'My\SpecialBundle\Entity\User', 'json');

throws:

"request.CRITICAL: Uncaught PHP Exception JMS\Serializer\Exception\RuntimeException: "You must define a type for FOS\UserBundle\Model\User::$username." at ...\vendor\jms\serializer\src\JMS\Serializer\GenericDeserializationVisitor.php line 170 [] []"

Whats wrong?! How can I deserialize the json to a user object correctly? I use symfony 2.3

Most helpful comment

Anyone else that stumbles upon this issue and is using annotations:

Class Model
{
    /**
     * @ORM\Column(type="boolean", nullable=true)
     * @Type("boolean")
     */
    protected $property;
}

All 14 comments

Well, the error message tells you what you need to do: You must define a type for FOS\UserBundle\Model\User::$username.

How should I define that type? In my User class that extends fosuser base class I have no $username, its defined in the parent class.

Use XML or YAML to define the metadata for the FOSUserBundle class (you cannot use annotations as it would require modifying the FOSUserBundle source code, which is a bad idea). Here is how I configured it in my project:

# app/config/config.yml
jms_serializer:
    metadata:
        directories:
            - { path: '%kernel.root_dir%/Resources/FOSUserBundle/serializer', namespace_prefix: 'FOS\UserBundle' }
# app/Resources/FOSUserBundle/serializer/Model.User.yml
FOS\UserBundle\Model\User:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        username:
            expose: true
        email:
            expose: true
        enabled:
            expose: true
        locked:
            expose: true

Added your code but problem remains. I still get the same error.

My code shows how to provide mapping for classes in vendor packages. But you still need to map the type. My config above copied from my project does not specify it as I never deserialize the user, I only serialize it.

Well but how do I define that type? I can define a type for my own attributes, but what about the attributes inherited from BaseUser (they have no type annotation)?

@ArtworkAD Define it in YAML instead of annotations

Ok it seems that it is working now. But last_login field is not exposed. Any ideas why?

FOS\UserBundle\Model\User:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        username:
            type: string
            expose: true
        usernameCanonical:
            type: string
            exclude: true
        email:
            type: string
            expose: true
        enabled:
            type: boolean
            expose: true
        locked:
            type: boolean
            expose: true
        last_login:
            type: datetime
            expose: true
        updated_at:
            type: datetime
            expose: true
        created_at:
            type: datetime
            expose: true

To expose/exclude my custom user attributes I have to define a User.yml in My/SpecialBundle/Resources/config/serializer?

@ArtworkAD for your own class, you can choose the format you want: YAML, XML or annotations

@stof ok. When I remove created_at and updated_at from app/Resources/FOSUserBundle/serializer/Model.User.yml they are still exposed. Very strange, any ideas why this happens? Do I have to exclude them explicitly?

These fields are not defined in FOS\UserBundle\Model\User. You need to configure them in the mapping of the right class

The default exclusion policy is none, so properties are exposed unless blacklisted (I changed it to a whitelist in my config of FOS\UserBundle\Model\User above to make it shorter)

Thank you, I had a typo, it is lastLogin instead of last_login, and type is DateTime instead of datetime. Now it works.

Anyone else that stumbles upon this issue and is using annotations:

Class Model
{
    /**
     * @ORM\Column(type="boolean", nullable=true)
     * @Type("boolean")
     */
    protected $property;
}

Similarly if you are trying to de-serialize objects like the OP, this worked for me:

use App\MyClass;

class Model
{
    /**
     * @var MyClass
     * @Type(MyClass::class)
     */
    private $property;
}
Was this page helpful?
0 / 5 - 0 ratings