0
votes

I got the serializer in Symfony working, i can GET and POST json with the EntityController. I have an edit form where an existing object/entity can be edited and saved. When the edited object gets posted (as a json object) the json objects gets deserialized, persisted and flushed tot the database. So far so good, at least as long as i dont post associated (ManyToMany) entities.

I have two entities (with a ManyToMany association):

  1. Object

  2. Element

This works (see also the jsonEditAction in the controller(posted below)):

{
    "id": "1",
    "name": "object 1"
}

My question is: How can i edit the object with associated entities in the json, like this:

{
    "id": "1",
    "name": "object 1",
    "elements": {
        "0": "1",
        "1": "2"
    }
}

When i post the above json i get the following notice from Symfony:

"message": "Expected argument of type \"AppBundle\Entity\Element\", \"integer\" given", "class": "Symfony\Component\PropertyAccess\Exception\InvalidArgumentException",

For further information; this is the editAction where the Json is posted to:

public function jsonEditAction(Request $request, $id) {
    $serializer = $this->initSerializer();
    $em = $this->getDoctrine()->getManager();

    $object = $em->getRepository('AppBundle:Object')->findOneById($id);

    $data = $request->getContent();

    $serializer->deserialize($data, 'AppBundle\Entity\Object', 'json', array('object_to_populate' => $object));

    try {
        $em->persist($object);
        $em->flush();

        $view = $this->view($object, 200)
                ->setTemplate("object/json.html.twig");
    } catch (Exception $e) {
        $view = $this->view('Caught exception: ' . $e->getMessage() . "\n", 500)
                ->setTemplate("object/json.html.twig");
    }

    return $this->handleView($view);
}

private function initSerializer() {
    $encoders = array(new JsonEncoder());
    $normalizers = array(new ObjectNormalizer());

    $serializer = new Serializer($normalizers, $encoders);

    return $serializer;
}   `

Should i walk to the array with elements and find them one by one and then add them to the 'object' entity? Or is there a 'build-in' solution in the serializer that i missed/ didn't see?

UPDATE: Also the JSON like suggested by Alexey didn't work:

{
    "id": 2,
    "name": "Object 2c",
    "elements": [{
        "id": 1
    }, {
        "id": 2
    }]
}

UPDATE: My question is a duplicate of: Deserialize an entity with a relationship with Symfony Serializer Component There is a pull request created and will be merged in Symfony 3.2...

1
May be your are looking for Symfony Data transformerJeet
But as long as serializer is concerned, It should handle transformer implicitly, I used JMSSerializer with FOSRestBundle. But I never faced any such issue. That is because, even the data were being submitted in clean JSON, I always used a form type to handle the post data.Jeet
@Jeet: can you show me an example of your handler?Lex Hartman
There is no handler as such, FOSRestBundle handles that with providing events to overwrite. I would suggest, use of form type to capture entity association related data. The form will transform data automatically for you.Jeet

1 Answers

0
votes

You have a bad JSON, Symfony says you the same.

A good JSON can look like this:

{
    "id": "1",
    "name": "object 1",
    "elements": [
        {"id": "254", "name": "element 254"},
        {"id": "301", "name": "element 301"}
    ]
}

Symfony tries to deserialize an Element object from "1" and "2" in your original JSON and fails.