Расшифровка JSON в Twig

Можно ли декодировать JSON в веточку? Похоже, что поиск в Google ничего не дает. Разве расшифровка JSON в Twig не имеет смысла?


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

После того, как я наткнулся на два предыдущих вопроса 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 это в ветке...

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

8 ответов

Решение

Это легко, если вы продлите веточку.

Сначала создайте класс, который будет содержать расширение:

<?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 %}

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

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

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


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

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

{% for r is res %}
    {{ r }}
{% endfor %}

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

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

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

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

Поэтому перед тем, как передать макеты $ в шаблон веточки, я сделал следующее:

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

сделав это, я создал переменную "на лету" внутри моего объекта под названием "decoded", которая содержит декодированный объект json.

Так что теперь в моем шаблоне я могу получить доступ к своим элементам json с помощью {{ layout.decoded.whwhat}}

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

Обновленный код для 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'),
        ];
    }
}

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

Использование:

установите 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

Просто оставлю это здесь:

если кто-то пытается передать json расширению ветки ... и они не могут его сформулировать, потому что он экранирован и т. Д. это может быть именно то, что они после.

      $data_array = json_decode(html_entity_decode($data_string), true);

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

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

Для 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}
Другие вопросы по тегам