title: How to access JSON data in a twig template?
body: <p>I'm using Symfony2 and making a php curl request to an api. I'm looking to make sure the results are being returned in the correct form: as a <code>json</code> <strong>string</strong> (not a php object or something else). The returned <code>json</code> string is consumed by renderAPIResults() that uses twig to "render" a <code>JsonResponse</code>. Is this possible? </p>
  
  <p>Can I <strong>"render"</strong> the response in <code>renderAPIResults</code> or do I need to return a <code>JsonResponse</code> and have the twig template render it, having been called from apiAction()?</p>
  
  <p>Is there any built in Symfony2 functionality wherein if one names a template <code>results.json.twig</code> vs. <code>results.html.twig</code>, or is this naming convention is just idiomatic?</p>
  
  <p>I have been able to get the results into results.html.twig by rendering a <code>Response()</code> in the <code>renderAPIResults()</code> method but I have only been able to <code>console.log()</code> the results from a <code>.js</code> file when returning the results as a <code>JsonResponse()</code>.  I have not been able to parse these results in any shape or form in the <code>results.json.twig</code> template when trying to somehow 'render' a <code>JsonResponse</code>.</p>
  
  <pre><code>     //DefaultController.php
       public function curlRestRequest($apiQueryString, $jsonDecode = FALSE, array $post_data = null, $service_url = null){
  
          if(!$service_url) {
              $service_url = 'http://website.com/rest';
          }
  
          $curl = curl_init($service_url.$apiQueryString);
  
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($curl, CURLOPT_POST, true);
          curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
  
          $curl_response = curl_exec($curl);
  
          if ($curl_response === false) {
              $info = curl_getinfo($curl);
              curl_close($curl);
              die('error occured during curl exec. Additioanl info: ' . var_export($info));
          }
          curl_close($curl);
  
          if($jsonDecode)
          {
              $curl_response = json_decode($curl_response);
          }
  
          return $curl_response;
      }
  
      public function renderAPIResults($data, $asObject = FALSE, $template)
      {
          if(!$template) {
              throw new Exception('Must provide a template name before rendering!');
          }
  
          if($asObject != TRUE) {
              // we want to cast to array since specified as OBJECT = FALSE, removing all instances of objects
              $dataArray = json_decode(json_encode($data), true);
              return $this-&gt;render($template, array('data' =&gt; $dataArray));
          } else { // Is JSON Decoded, if it is an object
              //just return json data, parse it in javascript instead of with template
  
              $response = new JsonResponse();
              $response-&gt;setData(array(
                  'data' =&gt; $data
              ));
              return $response;
              //return $this-&gt;renderView($template, array('data' =&gt; $data));
              //or
              //$content = $this-&gt;render($template, array('data' =&gt; $data));
              //return new JsonResponse($content);
          }
      }
  
      public function apiAction($type, $query){
        $apiQueryString = '/search/' . $type . '?query=' . $query;
  
        //make a curl request
        $requestedResults = ($this-&gt;curlRestRequest($apiQueryString, TRUE));
  
        //return option three: (dont use any response object, and just pass, just pass curl-results directly)
        //note, currently, when set as true, its not rendered in the template, the template is not used
        $view = $this-&gt;renderAPIResults($requestedResults, TRUE, 'ApiBundle:API:results.json.twig');
        return $view;
      }
  </code></pre>
  
  <p>This is the twig template:</p>
  
  <pre><code>    //results.json.twig
      {{ dump(data) }}
  </code></pre>
  
  <p>Basically, im asking:</p>
  
  <p>How do I utilize <code>JsonResponse()</code> in the <code>renderAPIResults()</code> method to render the <code>results.json.twig</code> in that same method, returning this rendered template <em>so the <strong>template itself</strong> can loop over the <code>json</code> results?</em></p>
  
  <p>Can I use <code>JsonResponse()</code> to render a template this way?   Or do I have to use only the <code>Response()</code> method when rendering?</p>
  
  <p>If I can't use <code>JsonResponse</code> to render, can I parse the results directly in twig using its native language? i.e. <code>{{ dump(results) }}</code> or do I need to include javascript inside scripts tags and process these results first?</p>
  
  <hr>
  
  <p>EDIT: I think i found a solution to the problem.  </p>
  
  <p>when you json_decode($string,TRUE), if its a deeply nested array, then the nested components don't end up as a perfect nested array as i assumed it would, only the top level ones do. Is this a natural side effect of json_decode, or bad json, or what am i doing wrong?  </p>
  
  <p>I think this post help shed some light on this. <a href="https://stackoverflow.com/questions/14934660/accessing-json-array-after-json-decode-multidimensional-array">Accessing JSON array after json_decode/multidimensional array</a></p>
  
  <p>So it appears the problem i was having was the JSON data wasnt completely clean. </p>
  
  <p>i.e. </p>
  
  <pre><code>    $requestedResults = ($this-&gt;curlRestRequest($apiQueryString, TRUE));
      print_r($requestedResults);
      //yields  Array
      (
          [category] =&gt; 
          [executionTime] =&gt; 759
          [facets] =&gt; 
          [resultCount] =&gt; 8
          [searchCount] =&gt; 0
          [searchInfo] =&gt; 
          [searchResults] =&gt; Array
              (
                  [0] =&gt; Array
                      (
                          [description] =&gt; Gives instructions for 3 different in-class games.
                          [taxonomyDataSet] =&gt; {"course":[],"topic":[],"unit":[],"lesson":[],"subject":[],"curriculum":{"curriculumName":["Common Core State Standards - Math","Common Core State Standards - Math"],"curriculumCode":["CCSS.M.8.G.C.9","CCSS.M.7.G.B.6"],"curriculumDesc":["Solve real-world and mathematical problems involving area, volume and surface area of two- and three-dimensional objects composed of triangles, quadrilaterals, polygons, cubes, and right prisms.","Know the formulas for the volumes of cones, cylinders, and spheres and use them to solve real-world and mathematical problems."]}}
      [thumbnail] =&gt; slides/thumbnail.jpg
                              [title] =&gt; Game Suggestions for Volume
                          )            
          )
  
  </code></pre>
  
  <p>which the "curriculumCode" for e.g. wasnt accessible, or anything in the taxonomyDataSet wasnt accessible, via twig, and i had to massage the data a bit to clean it.  </p>
  
  <pre><code>    $requestedResults = ($this-&gt;curlRestRequest($apiQueryString, TRUE));
  
          foreach ($requestedResults['searchResults'] as $resource) {
              $title = $resource["title"];
              $description = $resource["description"];
              $thumbnailUrl = $resource["thumbnails"]['url'];
              $taxonomyDataSet = json_decode($resource['taxonomyDataSet'],TRUE);
              $standard = $taxonomyDataSet['curriculum']['curriculumCode'];
              if(! file_exists($thumbnailUrl))
              {
                  $thumbnailUrl = NULL;
              }
  
              $results[] = array($title,$description,$thumbnailUrl, $standard);
          }
      print_r($results);
  
      //yields
      Array
      (
      [0] =&gt; Array
          (
              [0] =&gt; Game Suggestions for Volume
              [1] =&gt; Gives instructions for 3 different in-class games.
              [2] =&gt; 
              [3] =&gt; Array
                  (
                      [0] =&gt; CCSS.M.8.G.C.9
                      [1] =&gt; CCSS.M.7.G.B.6
                  )
  
          ))
  </code></pre>
  
  <p>Why Am i having to take this extra step, isn't there a better way to properly iterate over a JSON string so this doesnt happen?  </p>
  
  <p>I would MUCH prefer keeping it an object, then simple return it like this in the controller <code>return $requestedResults-&gt;searchResults</code> 
  where i can safely iterate it in TWIG without all the data massaging. </p>
  
  <p>Edit, ok looking into this once again deeper, i believe that the company's API data is to blame, it looks like one particular portion of the results is double json_encoded, and this make sense why the data is not accessible until i massage it.  is it me, or does it appear that this is whats happening?</p>