Symfony 4.3中如何在Twig模板内解码JSON数据?
你碰到的这个问题很典型——Symfony 4+ 配套的Twig版本默认已经移除了json_decode过滤器,早年Symfony2的老方案自然就不适用了。下面给你几个适配Symfony4.3的靠谱解决办法,按推荐程度排序:
方案1:在实体中添加数据访问器(推荐,符合Symfony最佳实践)
这种方法把数据解码逻辑放在实体层,模板直接调用处理好的数据,既清晰又易维护。
首先在你的ApplicationForm实体类中,新增一个方法来解码jsonData字段:
// src/Entity/ApplicationForm.php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; class ApplicationForm { // ... 你的其他字段、getter/setter代码 /** * @ORM\Column(type="json") // 如果你的字段是string类型,把这里改成type="string"即可 */ private $jsonData; // ... 原有的getJsonData()方法 public function getDecodedJsonData(): array { // 解码为关联数组,第二个参数传true;如果要返回对象就传false return json_decode($this->jsonData, true) ?? []; } }
划重点:如果你的
jsonData字段在Doctrine里定义的是json类型,Doctrine会自动帮你把字段解码成数组/对象,这时候你甚至不需要自己写getDecodedJsonData,直接在模板里用data.jsonData.fname就行!
然后在Twig模板里直接调用处理好的数据,同时纠正你之前的语法错误(原模板里的{% for json is a %}是错误写法,因为解码后是单个对象,不需要循环):
{% for data in form %} {% set decodedData = data.decodedJsonData %} {{ decodedData.fname }} {{ decodedData.lname }} <br> {% endfor %}
方案2:自定义Twig过滤器(适合多模板复用场景)
如果需要在多个模板里使用json_decode功能,可以自定义一个Twig过滤器,Symfony4.3的配置非常简单:
- 创建Twig扩展类:
// src/Twig/JsonDecodeExtension.php namespace App\Twig; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; class JsonDecodeExtension extends AbstractExtension { public function getFilters(): array { return [ new TwigFilter('json_decode', [$this, 'jsonDecode']), ]; } public function jsonDecode(string $json, bool $assoc = true): array { $decoded = json_decode($json, $assoc); // 处理解码失败的情况,返回空数组避免报错 return $decoded === null ? [] : $decoded; } }
- 无需额外配置:Symfony4.3默认开启了
autoconfigure,这个类会自动被注册为服务,直接用就行。
之后你就能在Twig里按原来的思路使用了,记得修正循环错误:
{% for data in form %} {% set a = data.jsonData | json_decode %} {{ a.fname }} {{ a.lname }} <br> {% endfor %}
方案3:在控制器中提前处理数据(快速临时解决方案)
如果只是临时需求,不想改实体或写扩展,可以在控制器里先把数据解码好再传给模板:
public function testoutput($id) { $forms = $this->getDoctrine()->getRepository(ApplicationForm::class)->findAll(); // 遍历处理每个表单数据,添加解码后的字段 $processedForms = array_map(function($form) { $decoded = json_decode($form->getJsonData(), true) ?? []; return [ 'form' => $form, 'decodedData' => $decoded ]; }, $forms); return $this->render('testoutput.html.twig', array('forms' => $processedForms)); }
对应的模板代码:
{% for item in forms %} {{ item.decodedData.fname }} {{ item.decodedData.lname }} <br> {% endfor %}
内容的提问来源于stack exchange,提问作者JBA
相关产品推荐
相关产品推荐

