Как заставить JinJava выдавать ошибку, если не удается найти привязку

Мне нужно использовать 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 каждый раз?

2 ответа

Вы можете сделать что-то вроде этого,

      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 что вы, возможно, захотите проверить.

Основываясь на вашем решении с фильтрами токенов, я сделал это, зарегистрировав для этой цели специальные теги.

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]

или бросает:

### java.lang.IllegalArgumentException: TemplateError{severity=FATAL, reason=SYNTAX_ERROR, message=UnknownTagException: Syntax error in '{% unrendered %}': Unknown tag: unrendered, fieldName=null, lineno=2, item=OTHER}
Другие вопросы по тегам