Posting JSON objects to Symfony 2

78,174

Solution 1

If you want to retrieve data in your controller that's been sent as standard JSON in the request body, you can do something similar to the following:

public function yourAction()
{
    $params = array();
    $content = $this->get("request")->getContent();
    if (!empty($content))
    {
        $params = json_decode($content, true); // 2nd param to get as array
    }
}

Now $params will be an array full of your JSON data. Remove the true parameter value in the json_decode() call to get a stdClass object.

Solution 2

I wrote method to get content as array

protected function getContentAsArray(Request $request){
    $content = $request->getContent();

    if(empty($content)){
        throw new BadRequestHttpException("Content is empty");
    }

    if(!Validator::isValidJsonString($content)){
        throw new BadRequestHttpException("Content is not a valid json");
    }

    return new ArrayCollection(json_decode($content, true));
}

And I use this method as shown below

$content = $this->getContentAsArray($request);
$category = new Category();
$category->setTitle($content->get('title'));
$category->setMetaTitle($content->get('meta_title'));

Solution 3

javascript on page:

function submitPostForm(url, data) {
    var form                = document.createElement("form");
        form.action         = url;
        form.method         = 'POST';
        form.style.display  = 'none';

    //if (typeof data === 'object') {}

    for (var attr in data) {
        var param       = document.createElement("input");
            param.name  = attr;
            param.value = data[attr];
            param.type  = 'hidden';
        form.appendChild(param);
    }

    document.body.appendChild(form);
    form.submit();
}

after some event (like a click on "submit"):

// products is now filled with a json array
var products = jQuery('#spreadSheetWidget').spreadsheet('getProducts');
var postData = {
'action':   action,
'products': products
}
submitPostForm(jQuery('#submitURLcreateorder').val(), postData);

in the controller:

   /**
    * @Route("/varelager/bestilling", name="_varelager_bestilling")
    * @Template()
    */
   public function bestillingAction(Request $request) {
       $products   = $request->request->get('products', null); // json-string
       $action     = $request->request->get('action', null);

       return $this->render(
           'VarelagerBundle:Varelager:bestilling.html.twig',
           array(
               'postAction' => $action,
               'products' => $products
           )
       );
   }

in the template (bestilling.html.twig in my case):

  {% block resources %}
       {{ parent() }}
       <script type="text/javascript">
       jQuery(function(){
           //jQuery('#placeDateWidget').placedate();
           {% autoescape false %}
           {% if products %}

           jQuery('#spreadSheetWidget').spreadsheet({
               enable_listitem_amount: 1,
               products: {{products}}
           });
           jQuery('#spreadSheetWidget').spreadsheet('sumQuantities');
           {% endif %}
           {% endautoescape %}

       });
       </script>
   {% endblock %}

Alrite, I think that's what you wanted :)

EDIT To send something without simulating a form you can use jQuery.ajax(). Here is an example in the same spirit as above which will not trigger a page refresh.

jQuery.ajax({
    url:        jQuery('#submitURLsaveorder').val(),
    data:       postData,
    success:    function(returnedData, textStatus, jqXHR ){
        jQuery('#spreadSheetWidget').spreadsheet('clear');
        window.alert("Bestillingen ble lagret");
        // consume returnedData here

    },
    error:      jQuery.varelager.ajaxError, // a method
    dataType:   'text',
    type:       'POST'
});
Share:
78,174
greg
Author by

greg

Symfony2 Developer

Updated on July 05, 2022

Comments

  • greg
    greg almost 2 years

    I'm working on a project using Symfony 2, I've built a bundle to handle all my database services which passes JSON data back and forward.

    My Problem/Question:

    • Is it possible to post a straight up JSON object? Currently I'm spoofing a normal form post for my ajax calls by giving the object a name json={"key":"value"} if I don't give it a name I can't seem to get the data from the Symfony request object $JSON = $request->request->get('json');

    • I want to be able to use the one service bundle to handle both data coming from AJAX calls, or a normal Symfony form. Currently I'm taking the submitted Symfony form, getting the data then using JSON_ENCODE, I just can't work out how to post the data through to my services controller which is expecting request data.

    To summarise:

    • I want Symfony to accept a JSON post object rather than a form.

    • I want to pass the JSON object between controllers using Request/Response

    If I'm going about this all wrong, feel free to tell me so!

  • greg
    greg about 12 years
    Thanks for the speedy response! Essentially you are still submitting a normal form with javascript, that is kind of what i'm doing at the moment, I was wondering whether it was possible to directly post the JSON object without simulating a form, if not no drama. Also, once I have the JSON object in Symfony, is it possible to send it off to another service as a Request object?
  • Ярослав Рахматуллин
    Ярослав Рахматуллин about 12 years
    I addressed your comment in my edit. I'm not quite sure how to do ajax stuff without jQuery, so ill leave that to you. To send someone to another controller you can redirect them there. This is covered in symfony.com/doc/2.0/book/controller.html under Redirecting and Forwarding. Good luck!
  • greg
    greg about 12 years
    Thank you again, I should have been a little clearer, I can submit the object no problems, I just can't work out how to retrieve it in the controller without it having a name
  • greg
    greg about 12 years
    Thanks for the response. I actually got it working over the weekend this way: $JSON = file_get_contents("php://input"); Any problems doing it this way?
  • richsage
    richsage about 12 years
    php://input is a one-time read only. Once you've read the content, it's not available to read again unless you pass that data around. Using the Symfony2 Request object ensures that you can get the data again during a request should you need to, without passing eg your $JSON variable around.
  • greg
    greg about 12 years
    Thanks for the explanation! I have changed to your method and it's working perfectly. Thank you.
  • greg
    greg about 12 years
    One small typo with the answer. The function needs the request parameter: public function yourAction(Request $request)
  • richsage
    richsage about 12 years
    @whistlergreg No probs! :-) Passing the request object in via the parameters is optional; you should be able to leave it out and get it from the container as per the code above, or pass it in. See here and here for the different variants.
  • Vitaliy Lebedev
    Vitaliy Lebedev almost 11 years
    there is one problem with this one: you can't bind such request to a form. Is there a way to do so ?
  • Hugo Nogueira
    Hugo Nogueira almost 10 years
    Thanks for your answer. Did a lot of search before landing here to discover ->getRequest()->getContent() to get my Request Payload parameters. Thanks!
  • Bill'o
    Bill'o over 9 years
    $request->request->get('action', null) equals to $request->request->get('action') of course
  • Felix Aballi
    Felix Aballi over 9 years
    If you use JSON.stringify({'key1': 'value1'}) in ajax request. The controller will receive it as json object, the other case sends: "key1=value1&key2=value2", query string. And will be necessary use the $request->get('key1'). I think the first one is cleaner.
  • Felix Aballi
    Felix Aballi over 9 years
    If you use JSON.stringify({'key1': 'value1'}) in ajax request. The controller will receive it as json object, the other case sends: "key1=value1&key2=value2", query string. And will be necessary use the $request->get('key1'). I think the first one is cleaner.
  • Mohamed Radhi Guennichi
    Mohamed Radhi Guennichi over 6 years
    The validator class exists by default on symfony?
  • Ярослав Рахматуллин
    Ярослав Рахматуллин about 6 years
    arrays don't have methods, bro.
  • Farid Movsumov
    Farid Movsumov about 6 years
    ArrayCollection is a class.
  • Girts Strazdins
    Girts Strazdins over 5 years
    this solution is deprecated. use solution suggested by Farid instead: use Request $request as parameter for the controller method, then read the JSON body as $request->getContent()