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 %}
Best Answer
That's easy if you extend twig.
First, create a class that will contain the extension:
<?phpnamespace 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 %}
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.
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.
<?phpfunction 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 %}
Updated code for Symfony2.8 or Symfony3:
<?phpnamespace 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';}// Note: If you want to use it as {{ json_decode(var) }} instead of // {{ var|json_decode }} please use getFunctions() and // new \Twig_SimpleFunction('json_decode', 'json_decode') public function getFilters() {return [// Note that we map php json_decode function to // extension filter of the same namenew \Twig_SimpleFilter('json_decode', 'json_decode'),];}}
This is an old question but I'm adding my solution for the record... Just extend Twig with a SimpleFunction:
// Return a string of separated values from a JSON string// Can optionally specify a separator. If none provided, ", " is used.$function = new Twig_SimpleFunction('json_to_list', function($json, $separator = ", "){$result = "";$array = json_decode($json, true);foreach ($array as $item){if ($result != "") { $result .= $separator; } $result .= $item;}return $result;});$twig->addFunction($function);
Usage:
set a_json_variable to the string '["1","2","3","4","5"]' before calling the Twig render.
Twig template:
The values are: {{ json_to_list(a_json_variable) }}
Will produce
The values are: 1, 2, 3, 4, 5
Just going to leave this here:
if some one is trying to pass json to a twig extension ..and they can't phrase it because its escaped ect.this may be just what they are after.
$data_array = json_decode(html_entity_decode($data_string), true);
In my case i have got an JsonArray in my Entity then i've add in my Entity a methode
<?phpnamespace ACME\DefaultBundle\Entity;/*...*/ public function getDecodedPath(){return json_decode($this->path);}