Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decoding JSON in Twig

Tags:

php

twig

symfony

Is is possible to decode JSON in twig? Googling doesn't seem to yield anything about this. Does decoding JSON in Twig not make sense?


I'm trying to access 2 entity properties on an Symfony2's entity field type (Entity Field Type).

After coming across 2 previous SO questions ( Symfony2 entity field type alternatives to "property" or "__toString()"? and Symfony 2 Create a entity form field with 2 properties ) which suggested adding an extra method to an entity to retrieve a customized string rather than an entity attribute, I thought of (and did) returning a JSON string representing an object instance.

Somewhere in the entity class:

/**
 * Return a JSON string representing this class.
 */
public function getJson()
{
   return json_encode(get_object_vars($this));
}

And in the form (something like):

$builder->add('categories', 'entity', array (
...
'property' => 'json',
...
));

Afterwards, I was hoping to json_decode it in Twig...

{% for category in form.categories %}
    {# json_decode() part is imaginary #}
    {% set obj = category.vars.label|json_decode() %}
{% endfor %}
like image 650
Czar Pino Avatar asked Jan 24 '13 11:01

Czar Pino


3 Answers

That's easy if you extend twig.

First, create a class that will contain the extension:

<?php
 
namespace Acme\DemoBundle\Twig\Extension;

use Symfony\Component\DependencyInjection\ContainerInterface;  
use \Twig_Extension;

class VarsExtension extends Twig_Extension
{
    protected $container;
 
    public function __construct(ContainerInterface $container) 
    {
        $this->container = $container;
    }
      
    public function getName() 
    {
        return 'some.extension';
    }
    
    public function getFilters() {
        return array(
            'json_decode'   => new \Twig_Filter_Method($this, 'jsonDecode'),
        );
    }

    public function jsonDecode($str) {
        return json_decode($str);
    }
}

Then, register that class in your Services.xml file:

<service id="some_id" class="Acme\DemoBundle\Twig\Extension\VarsExtension">
        <tag name="twig.extension" />
        <argument type="service" id="service_container" />
</service>

Then, use it on your twig templates:

{% set obj = form_label(category) | json_decode %}
like image 146
ButterDog Avatar answered Oct 28 '22 18:10

ButterDog


I came up with a way of getting to my JSON and I thought I'd share it here in case its usefult to someone else.

so in my case I have maybe 10 records (layouts) returned from a mysql db and each row has a field called properties which is a json string. So, I can easily pull out the records and send them to the template like so:

echo $twig->render('template.html.twig', array(
      "layouts" => $layouts,
));

So far so good, However when I do my {% for layout in layouts %} in twig there is no way to get to the properties field items as they are still a json string.

So just before I passed $layouts to the twig template I did the following:

foreach($layouts as $i => $v)
{
      $layouts[$i]->decoded = json_decode($v->getProperties());
}

by doing this Ive created a variable on the fly within my object called 'decoded' which contains the json decoded object.

So now in my template I can access my json items by {{ layout.decoded.whatever }}

This might be a bit hacky and not to everyones idea of a good solution. I works well for me, very little overhead and means I dont have to mess about with extending twig as Im doing the work before it gets to the template.

like image 6
azzy81 Avatar answered Oct 28 '22 20:10

azzy81


An alternative to all above.
And I don't know whether this is the optimal solution, but it works.

1) Create a helper function and register that function it.

<?php
function twig_json_decode($json)
{
    return json_decode($json, true);
}


2) Use this function in your twig file.

{% set res = twig_json_decode(json) %}
# above will return an array which can be iterated

{% for r is res %}
    {{ r }}
{% endfor %}
like image 6
Parag Tyagi Avatar answered Oct 28 '22 18:10

Parag Tyagi