我需要使用JinJava来处理可以包含不同标记的小模板。例如:
Hello,{{ user }}...
其中需要绑定user
,因为没有它,输出就没有任何意义。
我的类不知道令牌模板使用了什么,它从远程服务获取绑定列表。
因此,可能存在模板中指定的绑定不存在的情况。 JinJava的默认行为是使用在输出字符串中转换为空字符串的null
。它在我的情况下不起作用,如果错过任何绑定,我需要抛出异常。
我目前的解决方案是使用自定义Filter
/**
* A filter for JinJava that verifies that a value is not null and if the value is null, writes a fatal error to interpreter's log
*/
public class RequiredFilter implements Filter {
@Override
public Object filter(Object var, JinjavaInterpreter interpreter, String... args) {
if (var == null) {
interpreter.addError(new TemplateError(TemplateError.ErrorType.FATAL, TemplateError.ErrorReason.MISSING, "Value of a required key is null", "", 1, null));
}
return var;
}
@Override
public String getName() {
return "required";
}
}
让客户端为模板中的所有令牌显式指定此函数。上面的示例现在看起来像:
Hello, {{ user|required }}...
如果绑定user
不存在,我会得到异常。但是,自定义函数的要求看起来很奇怪。
有没有办法设置JinJava来实现类似的行为,并且每次都需要指定过滤器required
而不打扰客户?
答案 0 :(得分:1)
基于带有令牌过滤器的解决方案,我为此目的注册了自定义标签。
//my-template.phtml
<?php
use MyNamespace\Block\CustomBlocks
/** @var CustomBlocks $block */
class OneRandomClass {
}
?>
输出:
public static String fillTemplateTagsWithProperties(
String template, Map<String, String> properties) throws IllegalArgumentException
{
if (template == null) throw new IllegalArgumentException("template is null");
Jinjava jinjava = new Jinjava();
properties.forEach((k, v) -> jinjava.getGlobalContext().registerTag(new Tag() {
@Override
public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
if (v == null) {
interpreter.addError(new TemplateError(
TemplateError.ErrorType.FATAL,
TemplateError.ErrorReason.MISSING,
"Value of a required key is null",
k, 1, null));
}
return v;
}
@Override
public String getEndTagName() {
return null;
}
@Override
public String getName() {
return k;
}
}));
RenderResult renderResult = jinjava.renderForResult(template, properties);
if (renderResult.getErrors().size() == 0) {
return renderResult.getOutput();
} else {
throw new IllegalArgumentException(renderResult.getErrors().stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
}
@Test
public void jinjavaWithCustomTags(){
String template = "Hallo {% hallo %}\n" +
"I am {% unrendered %}";
Map<String, String> props = new HashMap<>();
props.put("hallo", "Welt");
//props.put("unrendered", "[try null here]");
System.out.println(fillTemplateTagsWithProperties(template, props));
}
或抛出:
Hallo Welt
I am [try null here]
答案 1 :(得分:1)
你可以这样做,
JinjavaConfig jc = JinjavaConfig.newBuilder().withFailOnUnknownTokens(true).build();
Jinjava jinjava = new Jinjava(jc);
// set context and other processes and then render
RenderResult renderResult = jinjava.renderForResult(template, properties);
if (renderResult.getErrors().isEmpty()) {
return renderResult.getOutput();
} else {
throw new IllegalArgumentException(renderResult.getErrors().stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
您可能还想检查许多其他 JinjavaConfig
。