Установка значения делегата с помощью Groovy JsonBuilder
(Это дополнительный вопрос к вопросу, заданному здесь)
Я использую JsonBuilder Groovy для динамического генерирования следующего JSON:
{
"type": {
"__type": "urn",
"value": "myCustomValue1"
},
"urn": {
"__type": "urn",
"value": "myCustomValue2"
},
"date": {
"epoch": 1265662800000,
"str": "2010-02-08T21:00:00Z"
},
"metadata": [{
"ratings": [{
"rating": "NR",
"scheme": "eirin",
"_type": {
"__type": "urn",
"value": "myCustomValue3"
}
}],
"creators": [Jim, Bob, Joe]
}]
}
Используя этот код:
def addUrn(parent, type, urnVal) {
parent."$type" {
__type "urn"
"value" urnVal
}
}
String getEpisode(String myCustomVal1, String myCustomVal2, String myCustomVal3) {
def builder = new groovy.json.JsonBuilder()
builder {
addUrn(delegate, "type", myCustomVal1)
addUrn(delegate, "urn", "some:urn:$myCustomVal2")
"date" {
epoch 1265662800000
str "2010-02-08T21:00:00Z"
}
"metadata" ({
ratings ({
rating "G"
scheme "eirin"
addUrn(delegate, "_type", "$myCustomVal3")
})
creators "Jim", "Bob", "Joe"
})
}
return root.toString();
}
Код выбрасывает StackruError
из-за третьего звонка addUrn
(под вложенным ratings
элемент. Если я прокомментирую эту строку, она отлично работает (кроме того факта, что мне не хватает необходимого куска информации).
- Почему это происходит?
- Как установить делегата для непосредственного родителя, например
ratings
?
Я пытался использовать метакласс безрезультатно.
1 ответ
Решение
Это довольно некрасиво (LOL), но даст вам ожидаемый результат:
def addUrn(parent, type, urnVal) {
parent."$type" {
__type "urn"
"value" urnVal
}
}
String getEpisode(String myCustomVal1, String myCustomVal2, String myCustomVal3) {
def builder = new groovy.json.JsonBuilder()
def root = builder {
addUrn(delegate, "type", myCustomVal1)
addUrn(delegate, "urn", "some:urn:$myCustomVal2")
"date" {
epoch 1265662800000
str "2010-02-08T21:00:00Z"
}
"metadata" ([{([
"ratings" ([{
rating "G"
scheme "eirin"
this.addUrn(delegate, "_type", "$myCustomVal3")
}]),
creators ("Jim", "Bob", "Joe")
])}])
}
println builder.toPrettyString()
}
Заметка:-
- В предыдущем вопросе я ошибся, сказав, что делегат должен ссылаться на непосредственного родителя. На самом деле это относится к непосредственному родителю. Вместо этого мы должны обратиться к сценарию (который имеет
addUrn
метод) при вызове метода, следовательно, использованиеthis
при звонкеaddUrn
внутри рейтинги. В качестве альтернативы вы можете отправить "рейтинги" по методу, аналогичномуaddUrn
, - Использование и последовательность скобок, цепочки и квадратной скобки важны для того, что вы видите после "метаданных". Давать понять, что здесь будет громоздко. Но единственное, на что нужно обратить внимание, - это придерживаться основ использования вызовов методов, объявления списков и использования замыканий. Попробуйте сделать отступ для каждой фигурной скобки в каждой строке, чтобы получить магию.:)
- Причиной ошибки StackOverFlow было то, что метод
getEpisode
не смог добраться до методаaddUrn
который принадлежит сценарию.
Протестируйте его прямо в Groovy Web Console