在 Twig 中解码 JSON

Posted

技术标签:

【中文标题】在 Twig 中解码 JSON【英文标题】:Decoding JSON in Twig 【发布时间】:2013-01-08 04:06:08 【问题描述】:

是否可以在 twig 中解码 JSON?谷歌搜索似乎对此没有任何帮助。 没有意义吗?


我正在尝试访问 Symfony2 的实体字段类型 (Entity Field Type) 上的 2 个实体属性。

在遇到 2 个之前的 SO 问题(Symfony2 entity field type alternatives to "property" or "__toString()"? 和 Symfony 2 Create a entity form field with 2 properties)建议向实体添加一个额外的方法来检索自定义字符串而不是实体属性后,我想到(并且确实)返回一个 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',
...
));

之后,我希望在 Twig 中 json_decode 它...

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

【问题讨论】:

为什么不在 phpjson_encode() 呢? 是的,我愿意 json_encode(get_object_vars($this))。问题在于解码,因为它必须在 Twig 而不是 PHP 中。 我不熟悉 Twig/Symfony2,但你能在你的操作中解码它并将结果传递给你的 Twig 模板吗? 嗨@halfer,您无法访问控制器中的实体(Sf1 中的模型对象)。表单(使用$builder 构建)自行查询类别,我所能做的就是配置哪个属性将用于在要呈现的实际表单中标记它。 你知道你可以扩展 twig 并编写自定义过滤器吗? twig.sensiolabs.org/doc/advanced.html 【参考方案1】:

如果你extend twig,那很容易。

首先,创建一个包含扩展的类:

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

【讨论】:

以防万一有人在寻找 Services.yml 设置:acme_demo.twig.extension.vars_extension: class:Acme\DemoBundle\Twig\Extension\VarsExtension arguments: [@service_container] tags: - name: 'twig.extension' 如果你只使用没有框架的 Twig 会发生什么:( @Xocoatzin,我看看你的答案,这与我正在寻找的内容相关。但我也有一个问题。我过去做了一个 TWIG 扩展类,并在构造函数中使用:` public function __construct(\Twig_Environment $env) $this->environment = $env; ` ,我确实使用了$this-&gt;environment 稍后使用函数loadTemplate('...') 就可以了。在您的解决方案中,我对ContainerInterface 的使用感到有些困惑,我不明白需要[@service_container] 的参数吗? @nyluje 如果您不需要service_container(如果您不知道是否需要它,那么您不需要),您可以安全地删除它。从Services.xml 中删除&lt;argument... service_container..&gt; 行、__construct 的参数和正文、protected $container;use ...containerInterface【参考方案2】:

我想出了一种获取我的 JSON 的方法,我想我会在这里分享它,以防它对其他人有用。

所以在我的情况下,我可能从 mysql 数据库返回了 10 条记录(布局),并且每一行都有一个名为 properties 的字段,它是一个 json 字符串。因此,我可以轻松地提取记录并将它们发送到模板,如下所示:

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

到目前为止一切顺利,但是当我在 twig 中执行 % for layouts in layouts % 时,无法访问属性字段项,因为它们仍然是 json 字符串。

所以就在我将 $layouts 传递给 twig 模板之前,我执行了以下操作:

foreach($layouts as $i => $v)

      $layouts[$i]->decoded = json_decode($v->getProperties());

通过这样做,我在我的对象中动态创建了一个名为“decoded”的变量,其中包含 json 解码的对象。

所以现在在我的模板中,我可以通过 layout.decoded.whatever

访问我的 json 项目

这可能有点 hacky 并且不是每个人都认为好的解决方案。我对我来说工作得很好,开销很小,这意味着我不必在扩展树枝上弄乱,因为我在它到达模板之前就在做这项工作。

【讨论】:

采用类似方法的更好解决方案是创建一个接收解码 JSON 的视图模型/DTO【参考方案3】:

上述所有方法的替代方案。 而且我不知道这是否是最佳解决方案,但它有效

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 %

【讨论】:

【参考方案4】:

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'),
        ];
    

【讨论】:

【参考方案5】:

在我的情况下,我的实体中有一个 JsonArray,然后我在我的实体中添加了一个方法

<?php
namespace ACME\DefaultBundle\Entity;
/*...*/    
public function getDecodedPath()

    return json_decode($this->path);

【讨论】:

【参考方案6】:

这是一个老问题,但我正在添加我的解决方案以备不时之需......只需使用 SimpleFunction 扩展 Twig:

// 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"]'。

树枝模板:

The values are:  json_to_list(a_json_variable) 

会产生

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

【讨论】:

以上是关于在 Twig 中解码 JSON的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 Swift 中解码我的 JSON 文件?

如何在 Swift 4 中解码 JSON(JSON Web 令牌)?

如何在 Laravel 中解码 JSON 对象

在 Swift 中解码任意 JSON

解码复杂的 JSON?

来自localstorage的JSON无法在php中解码