Декодирование JSON в Twig

Можно ли декодировать JSON в веточке? Googling, похоже, ничего не дает об этом. Не имеет смысла декодирование JSON в Twig?


Я пытаюсь получить доступ к 2 свойствам объекта в типе поля сущности Symfony2 ( Тип поля Entity ).

После того, как вы встретите 2 предыдущих вопроса SO ( тип поля объекта Symfony2 альтернативы «property» или «__toString ()»? И Symfony 2 создайте поле формы сущности с 2 свойствами ), который предложил добавить дополнительный метод для объекта для извлечения настраиваемой строки а не атрибут сущности, я подумал о (и сделал), возвращая строку JSON, представляющую экземпляр объекта.

Где-то в классе сущностей:

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

И в форме (что-то вроде):

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

Впоследствии я надеялся на json_decode в Twig …

 {% for category in form.categories %} {# json_decode() part is imaginary #} {% set obj = category.vars.label|json_decode() %} {% endfor %} 

Это легко, если вы расширяете веточку .

Во-первых, создайте класс, который будет содержать расширение:

 <?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); } } 

Затем зарегистрируйте этот класс в файле Services.xml:

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

Затем используйте его на своих шаблонах ветви:

 {% set obj = form_label(category) | json_decode %} 

Я придумал способ добраться до своего JSON, и я подумал, что поделюсь с ним здесь, если он будет полезен кому-то другому.

поэтому в моем случае у меня есть, возможно, 10 записей (макетов), возвращаемых из mysql db, и каждая строка имеет поле, называемое свойствами, которое является json-строкой. Итак, я могу легко вытащить записи и отправить их в шаблон следующим образом:

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

До сих пор так хорошо, но когда я делаю свой {% для макета в макетах%} в ветке, нет способа добраться до элементов поля свойств, поскольку они все еще являются json-строкой.

Таким образом, перед тем, как передать $ layouts шаблону ветки, я сделал следующее:

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

сделав это, Ive создал переменную «на лету» в моем объекте под названием «декодированный», который содержит json-декодированный объект.

Итак, теперь в моем шаблоне я могу получить доступ к своим json-элементам {{layout.decoded.whatever}}

Это может быть немного взломанным, а не всякой идеей хорошего решения. Я хорошо работаю для меня, очень немного накладных расходов и означает, что мне не нужно путаться с расширением ветки, поскольку я делаю работу, прежде чем она попадет в шаблон.

Альтернатива всем вышеперечисленным.
И я не знаю, является ли это оптимальным решением, но оно работает .

1) Создайте вспомогательную функцию и зарегистрируйте ее функцию.

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

2) Используйте эту функцию в своем файле twig .

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

Обновленный код для Symfony2.8 или Symfony3:

 <?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'; } // 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 name new \Twig_SimpleFilter('json_decode', 'json_decode'), ]; } } 

В моем случае у меня есть JsonArray в моей Entity, тогда я добавляю в свою Entity метод

 <?php namespace ACME\DefaultBundle\Entity; /*...*/ public function getDecodedPath() { return json_decode($this->path); } 

Это старый вопрос, но я добавляю свое решение для записи … Просто растяните Twig с помощью 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); 

Применение:

перед вызовом рендеринга Twig установите a_json_variable в строку '["1", "2", "3", "4", "5"]'.

Шаблон Twig:

 The values are: {{ json_to_list(a_json_variable) }} 

Будет производить

 The values are: 1, 2, 3, 4, 5 

Для Symfony 3.1, как говорит официальный документ , для этой цели есть помощник: return $this->json() :

 /** * @Route("/", name="homepage") * @Method({"GET","POST"}) */ public function indexAction() { $person = new Person(); $form = $this->createForm(PersonType::class, $person,[ 'action'=>$this->generateUrl('homepage'), 'method'=>'POST' ]); $form->handleRequest($request); if($form->isSubmitted() && $form->isValid()){ return $this->json([ 'name'=>$person->getName(), 'age'=>$person->getAge() ]); } return $this->render('default/index.html.twig',['form'=>$form->createView()]); } 

Результат выглядит так:

 {"name":"john","age":39}