Symfony 3 - How to handle a JSON request with a form

I find it difficult to determine how to handle a JSON request with Symfony forms (using v3.0.1).

Here is my controller:

/**
 * @Route("/tablet")
 * @Method("POST")
 */
public function tabletAction(Request $request)
{
    $tablet = new Tablet();
    $form = $this->createForm(ApiTabletType::class, $tablet);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($tablet);
        $em->flush();
    }

    return new Response('');
}

And my form:

class ApiTabletType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('macAddress')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\Tablet'
        ]);
    }
}

When I submit a POST request with the Content-Type header set correctly in application / json, my form is invalid ... all fields are null.

Here is the error message that I get if I comment out a line if ($form->isValid()):

An exception occurred while executing INSERT INTO (mac_address, site_id) VALUES (?,?) With parameters [null, null]:

I tried sending different JSON with the same result every time:

  • {"id":"9","macAddress":"5E:FF:56:A2:AF:15"}
  • {"api_tablet":{"id":"9","macAddress":"5E:FF:56:A2:AF:15"}}

"api_tablet" is what returns getBlockPrefix(Symfony 3 is equivalent to the form method getNamein Symfony 2).

Can someone tell me what I was doing wrong?


UPDATE:

getBlockPrefix . , :/

public function getBlockPrefix()
{
    return '';
}
+4
3
$data = json_decode($request->getContent(), true);
$form->submit($data);

if ($form->isValid()) {
    // and so on…
}
+6

FOSRestBundle.

, :

fos_rest:
    view:
        view_response_listener: force
        force_redirects:
          html: true
        formats:
            jsonp: true
            json: true
            xml: false
            rss: false
        templating_formats:
            html: true
        jsonp_handler: ~
    body_listener: true
    param_fetcher_listener: force
    allowed_methods_listener: true
    access_denied_listener:
        json: true
    format_listener:
        enabled: true
        rules:
            - { path: ^/, priorities: [ 'html', 'json' ], fallback_format: html, prefer_extension: true }
    routing_loader:
            default_format: ~
            include_format: true
    exception:
        enabled: true
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true

, getBlockPrefix ( , ):

public function getBlockPrefix()
{
   return 'api_tablet'
}

CSRF :

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'csrf_protection' => false,
        'data_class' => 'AppBundle\Entity\Tablet'
    ]);
}

:

{"api_tablet":{"macAddress":"5E:FF:56:A2:AF:15"}}

/:

  • , . , , .

  • camelCase. FOSRestBundle , , , -, .

0

I think you can drop forms and fill in-> check entities

$jsonData = $request->getContent();
$serializer->deserialize($jsonData, Entity::class, 'json', [
    'object_to_populate' => $entity,
]);
$violations = $validator->validate($entity);

if (!$violations->count()) {

    return Response('Valid entity');
}

return new Response('Invalid entity');

https://symfony.com/doc/current/components/serializer.html#deserializing-in-an-existing-object

https://symfony.com/components/Validator

0
source

Source: https://habr.com/ru/post/1622973/


All Articles