How to handle correctly JSON request in symfony?

24,879

Solution 1

I recommend the use of symfony-bundles/json-request-bundle since it does the JsonRequestTransformerListener for you. You just need to recieve the request parameters as usual:

...
$request->get('some_parameter');
...

Solution 2

hi you have to use service to make the Transformation

class php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class JsonRequestTransformerListener {


public function onKernelRequest(GetResponseEvent $event) {
    $request = $event->getRequest();
    $content = $request->getContent();
    if (empty($content)) {
        return;
    }
    if (!$this->isJsonRequest($request)) {
        return;
    }
    if (!$this->transformJsonBody($request)) {
        $response = Response::create('Unable to parse request.', 400);
        $event->setResponse($response);
    }
}


private function isJsonRequest(Request $request) {
    return 'json' === $request->getContentType();
}


private function transformJsonBody(Request $request) {
    $data = json_decode($request->getContent(), true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        return false;
    }
    if ($data === null) {
        return true;
    }
    $request->request->replace($data);
    return true;
}
 }

And In Your Service.yml

    kernel.event_listener.json_request_transformer:
    class: You\NameBundle\Service\JsonRequestTransformerListener
    tags:
        - { name: "kernel.event_listener", event: "kernel.request",method: "onKernelRequest", priority: "100" }

Now You can call The Default request function to get Data

$request->request->all();

Solution 3

You can use symfony ParamConverter to to convert the json into any object you want and raise a meaningful Exception if anything goes wrong.

You can add custom ParamConverters and use them in your actions with annotation

Share:
24,879
MatiRC
Author by

MatiRC

Updated on August 06, 2020

Comments

  • MatiRC
    MatiRC over 3 years

    I'm trying to handle this problem: My app send JSON POST request with several information encoded in a Json. Example:

    {"UserInfoA":{"1":123,"2":"hello","3":"bye","4":{"subinfo":1,"subinfo2":10}},
     "UserInfoB":{"a":"12345678","b":"asd"}} // and so on...
    

    each UserInfo have:

    • Its own entity (although some request may have information of more than one entity).
    • A controller to persist this Object on DB and then give back the ID on this DB.

    So, to achieve this problem I did another controller like JsonHandler, which receive this request and then forward to each controller after gut this JSON into differents objects. Example:

    public function getJson (Request $request){
        if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
                    $data = json_decode($request->getContent(), true);
                }
        if (!isset($data['UserInfoA'])){
             return new JsonResponse('ERROR');
                  }
        $uia = $data['UserInfoA'];
        $idInfoA = $this->forward('Path::dataAPersist',array('data'=>$uia));
            }
        // same with userinfoB and other objects
        return $idInfoA ;
    

    This works perfectly but Is it correct? Should i use services instead?

    EDIT : I need to response the ID in a Json and this->forward returns a Response, so i can't use JsonResponse and if a send directly $idInfoA just send the IDNUMBER not in a JSON, how can i do it?

    To sum up : a Json listener that receive the information, work it and then dispatch to the corresponding controller. This listener, should be a controller, a service or another thing?

    • svgrafov
      svgrafov over 6 years
      Well, this is too broad. You should rephrase the question. Clearly describe what you want your code to do.
    • MatiRC
      MatiRC over 6 years
      I want a module which handle JSON request and then send each Object (obtained after work with the JSON request) to the controllers that already exist to handle this object and persist in DB. So i made ANOTHER controller which have getJson method that do this and then call the respective methods in each controller.
    • LBA
      LBA over 6 years
      E.g. have a look at Symfony Serializer, JMS and FOS RestBundle
  • Dan
    Dan about 3 years
    This is the way