Исключение StreamingTemplateEngine MissingPropertyException - PullRequest
0 голосов
/ 14 мая 2018

Как избежать вхождения MissingPropertyException при отсутствии параметров из шаблона в Map и заменить не найденные значения на null?

import groovy.text.StreamingTemplateEngine
import groovy.text.Template

class Test {

    private static Writable binding(Map map, String string) {
        Template template = new StreamingTemplateEngine().createTemplate(string)
        return template.make(map)
    }

    static void main(String... args) {
        def template = "\${test1} \${test2}"
        def map = ["test1": "test1"]
        print binding(map, template)
    }
}

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

В качестве альтернативы вы можете просто использовать метод groovy Map.withDefault :

import groovy.text.StreamingTemplateEngine
import groovy.text.Template

def string = '''
Dear <% out.print firstname %> ${lastname},

We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> 
to inform you that your paper entitled
'$title' was ${ accepted ? 'accepted' : 'rejected' }.

The conference committee.
'''

def map = [
    firstname: 'test',
    lastname: 'test',
    accepted: true
].withDefault { "<not found>" }

Template template = new StreamingTemplateEngine().createTemplate(string)
println template.make(map)

, где единственным изменением кода OP является предложение withDefault.Выполняя вышеприведенные распечатки:

~> groovy test.groovy

Dear test test,

We are pleased
to inform you that your paper entitled
'<not found>' was accepted.

The conference committee.

В качестве примечания, я написал потоковый шаблонизатор в качестве вклада и ответа на ограничения других шаблонизаторов в то время, как нескольколет назадРад видеть, что это используется!

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

0 голосов
/ 14 мая 2018

Нет опции конфигурации для подавления этого исключения, однако вы можете расширить карту, которую вы передаете шаблону, и немного изменить ее поведение. Рассмотрим следующий пример:

import groovy.text.StreamingTemplateEngine
import groovy.text.Template

def string = '''
Dear <% out.print firstname %> ${lastname},

We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> 
to inform you that your paper entitled
'$title' was ${ accepted ? 'accepted' : 'rejected' }.

The conference committee.
'''

def map = [
    firstname: 'test',
    lastname: 'test',
    accepted: true
]

Template template = new StreamingTemplateEngine().createTemplate(string)
println template.make(map)

Сбой со следующим исключением:

Caught: groovy.text.TemplateExecutionException: Template execution error at line 4:
         3:     We <% if (accepted) out.print 'are pleased' else out.print 'regret' %>     to inform you that your paper entitled
     --> 4:     '$title' was ${ accepted ? 'accepted' : 'rejected' }.
         5:     

groovy.text.TemplateExecutionException: Template execution error at line 4:
         3:     We <% if (accepted) out.print 'are pleased' else out.print 'regret' %>     to inform you that your paper entitled
     --> 4:     '$title' was ${ accepted ? 'accepted' : 'rejected' }.
         5:     

    at test.run(test.groovy:21)
Caused by: groovy.lang.MissingPropertyException: No such property: title for class: groovy.tmp.templates.StreamingTemplateScript1
    ... 1 more

Сбой, потому что мы определили 3 из 4 шаблонных переменных (переменная title отсутствует).

Решение: создать оболочку для Map

Давайте исправим это. Мы сделаем это путем переопределения метода map containsKey(Object key) таким образом, чтобы он всегда возвращал true (этот метод используется механизмом шаблонов, и если он возвращает false, механизм шаблонов выдает исключение). Мы создадим класс-обертку, который инкапсулирует карту и делегирует вызов несуществующих методов этому обернутому классу. Мы назовем этот класс Bindings.

import groovy.text.StreamingTemplateEngine
import groovy.text.Template

class Bindings {
    @Delegate private final Map map

    Bindings(Map map) {
        this.map = map
    }

    boolean containsKey(Object key) {
        return true
    }
}

def string = '''
Dear <% out.print firstname %> ${lastname},

We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> 
to inform you that your paper entitled
'$title' was ${ accepted ? 'accepted' : 'rejected' }.

The conference committee.
'''

def map = [
    firstname: 'test',
    lastname: 'test',
    accepted: true
]

Template template = new StreamingTemplateEngine().createTemplate(string)
println template.make(new Bindings(map))

Выход:

Dear test test,

We are pleased 
to inform you that your paper entitled
'null' was accepted.

The conference committee.

Больше нет MissingPropertyException. Однако, как вы можете видеть, null печатается как null внутри строки. Если вы хотите вместо этого напечатать пустую строку, вы можете добавить Object get(Object key) метод к Bindings и переопределить его поведение по умолчанию:

class Bindings {
    @Delegate private final Map map

    Bindings(Map map) {
        this.map = map
    }

    boolean containsKey(Object key) {
        return true
    }

    Object get(Object key) {
        return map.getOrDefault(key, '')
    }
}

Если вы сделаете это, вы увидите вывод, похожий на:

Dear test test,

We are pleased 
to inform you that your paper entitled
'' was accepted.

The conference committee.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...