25

I have a json object that I received by making a get API call. I make this call to receive a list of objects. It's a list of post... So I have an array of Post Objects.

Here the output :

{
    "total":2,
    "data":[
      {
        "id":2,
        "user":{
          "id":1,
          "username":"sandro.tchikovani"             
        },
        "description":"cool",
        "nb_comments":0,
        "nb_likes":0,
        "date_creation":"2014-04-13T20:07:34-0700"
      },
      {
        "id":1,
        "user":{
           "id":1,
           "username":"sandro.tchikovani",
         },
        "description":"Premier pooooste #lol",
        "nb_comments":0,
        "nb_likes":0,
        "date_creation":"2014-04-13T15:15:35-0700"
      }
    ]
 }

I would like to deserialize the data part... The problem is that the Serializer in Symfony gives me an error ...

The error that I have :

Class array<Moodress\Bundle\PosteBundle\Entity\Poste> does not exist

How I do deserialize :

$lastPosts = $serializer->deserialize($data['data'], 'array<Moodress\Bundle\PosteBundle\Entity\Poste>', 'json');

How can I deserialze the data array... To have an array of Postes. I want to give to my view .twig an array Poste... I did precise the type when I deserialize... So I can't find what is the problem...

Thanks.

3
  • Did you get any further with your solution? I'm wondering how to get JMS to match such a data object within the json. Commented Jun 23, 2014 at 17:45
  • I didn't have choice... I just made a for each on the array, and deserialize the data for each value... I would have preferred to it another way, but I couldn't find any other solution. Commented Jun 24, 2014 at 4:58
  • Note for me in the future: old versions of Symfony serialiser (ex: 5.0.X) ignore the property types. We need to enforce the types with annotations (ex: /** @var \DateTime $date */). I suppose the latest version can find the type from PHP directly and not from the annotation comments. Commented Nov 27, 2024 at 13:26

6 Answers 6

27

Since Symfony Serializer Component 2.8 to deserialize array of objects:

$persons = $serializer->deserialize($data, 'Acme\Person[]', 'json');

https://symfony.com/doc/master/components/serializer.html#handling-arrays

Sign up to request clarification or add additional context in comments.

Comments

24

I think the best solution here is to create new PosteResponse class, like this one:

namespace Moodress\Bundle\PosteBundle\Response;

use JMS\Serializer\Annotation\Type;

class PosteResponse
{
    /**
     * @Type("integer")
     */
    private $total;

    /**
     * @Type("array<Moodress\Bundle\PosteBundle\Entity\Poste>")
     */
    private $data;

    //getters here
}

and deserialize your response to that class:

$response = $serializer->deserialize(
    $json,
    'Moodress\Bundle\PosteBundle\Response\PosteResponse',
    'json'
);
$posts = $response->getData();

That WILL do the trick, and it doesn't require you to decode and encode your json manually which is riddiculous in my opinion.

4 Comments

OP specifically asked about the Symfony Serializer not JMS Serializer.
@MikeDoe the same solution applies also to Symfony Serializer, just annotations are different.
Nope. There's no Type annotation in Symfony's serializer.
That's why I said "annotations are different". Still creating a different class for the response as a whole applies to Symfony Serializer as well as any other class-based serializer you can think of.
13

A less than ideal solution that I found was to first decode and then encode the json data again at the node that represents the data array. For example in your case:

$json = json_decode($json);
$json = json_encode($json->data);
$serializer->deserialize($json, 'array<Moodress\Bundle\PosteBundle\Entity\Poste>', 'json');

There must be a better solution than this but this seems more elegant than the above solution of de-serialising json.

1 Comment

Exactly what I needed. This should be the accepted answer.
9

The error is pretty clear. Your string does not match any existant class.

The example in official documentation says:

$person = $serializer->deserialize($data,'Acme\Person','xml');

In your case it should be more like:

$person = $serializer->deserialize($data['data'],'Moodress\Bundle\PosteBundle\Entity\Poste','json');

Update:

Ok then.

First, your json file does not seem to be valid (use http://jsonlint.com/ to test it). Be careful of that.

Second, you will have to fetch your json as an array with

$data = json_decode($yourJsonFile, true);

and then you can access to each 'data' array with

foreach($data['data'] as $result)
{
    /* Here you can hydrate your object manually like:
    $person = new Person();
    $person->setId($user['id']);
    $person->setDescription($user['description']);

    Or you can use a denormalizer. */
}

2 Comments

The problem is that $data['data'] is an array of Postes... Not just one... So I have to make understand to serializer that I want to deserialize an array of my entity type. Do you know what I mean?
Yeah, I thought about that... As ou said, it does the trick, but in the documentation it says that it's possible to serialize directly the array... If I don't find any other solution, I will do it by step like you did demonstrate. I just think it would be better to use the array type... But I don't know why, JMSSerialize doesn't like my code.
2

I would make something like this

class PostsModel
{
    /**
     * @var int
     */
    private $total;

    /**
     * @var PostModel[]
     */
    private $data;
}

class PostModel
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var UserModel
     */
    private $user;

    /**
     * @var string
     */
    private $description;

    /**
     * @var  int
     */
    private $nb_comments;

    /**
     * @var int
     */
    private $nb_likes;

    /**
     * @var \DateTime
     */
    private $date_creation;
}

class UserModel
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $username;
}

And in controller

            $posts = $this->serializer->deserialize($data, PostsModel::class, 'json');

And this will return $postsModel with $data property which will have your array of entities

Comments

1

In case someone will be searching how to decode an array of objects using Symfony Serializer:

use Moodress\Bundle\PosteBundle\Entity\Poste;

// your json data 
$data = '{
  "total":2,
  "data":[
    {...},
    {...}
  ]
}';

$lastPosts = $serializer->deserialize(
    $data['data'],
    'Moodress\Bundle\PosteBundle\Entity\Poste[]', // or Poste::class.'[]',
    'json'
);

Notice that you need to add [] after your class name, in this way Symfony will recognize your json data as an array of objects.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.