Я пытаюсь сгенерировать вывод JSON в Groovy (4.0.18) из общих запросов SQL, где запрос предоставляется во время выполнения.
Итак, я записал результаты SQL в список (наборов результатов), а имена столбцов записал в отдельный список (из строк).
Теперь мне просто нужно вывести его в формате JSON, и я хотел использовать JsonBuilder Groovy, поэтому я передал два списка в свой метод выводаJsonResults(), где я создаю JsonBuilder и пытаюсь перебрать набор результатов, используя технику, которой научил меня Пол Кинг с помощью XmlBuilder Groovy. в отдельном посте.
Вот простой пример -
List columns = [ "id", "val" ]
List resultSet = [
[ id:"id1", val:"val1" ],
[ id:"id2", val:"val2" ],
[ id:"id3", val:"val3" ]]
void outputJsonResults(columns, resultSet) {
def json = new groovy.json.JsonBuilder()
json {
queryResults(
resultSet.each { row ->
columns.each { col ->
"$col"(row[col])
}
}
)
}
println json.toPrettyString()
}
outputJsonResults(columns, resultSet)
Он работает и генерирует выходные данные JSON, но в дополнение к массиву наборов результатов в корне выходных данных JSON указан один случайный набор результатов, и я не могу понять, откуда он берется и как его устранить.
Вот сгенерированный результат:
{
"id": "id3",
"val": "val3",
"queryResults": [
{
"id": "id1",
"val": "val1"
},
{
"id": "id2",
"val": "val2"
},
{
"id": "id3",
"val": "val3"
}
]
}
И то, что я пытаюсь создать, это -
{
"queryResults": [
{
"id": "id1",
"val": "val1"
},
{
"id": "id2",
"val": "val2"
},
{
"id": "id3",
"val": "val3"
}
]
}
Любая помощь приветствуется.

То, что вы здесь называете, эффективно queryResults(resultSet)
плюс побочные эффекты, которые меняют построитель JSON. each возвращает
input (то есть оригинал resultSet) и выполняет замыкание для
побочные эффекты. Побочным эффектом здесь является изменение тока
JSON-Node, то же самое место, куда был добавлен queryResults.
Вы можете увидеть это, если замените вызов "$col"(row[col]) на
что-то еще, например bug("fix"). Тогда результат:
{
"bug": "fix",
"queryResults": [
{
"id": "id1",
"val": "val1"
}, {}, {}
]
}
(или добавьте больше пар ключ-значение в свой набор макетов результатов).
Вам необходимо collect (для списка карт) и subMap/collectEntries.
(для карт) вместо этого:
json {
queryResults(
resultSet.collect { row ->
// pick this:
row.subMap(columns)
// or this:
columns.collectEntries { col ->
[col, row[col]]
}
}
)
}
Вы можете использовать оператор распространения, чтобы сделать это более кратким: queryResults(resultSet*.subMap(columns))
Спасибо! Это прекрасно работает (конечно), и я изучу ваше объяснение (спасибо за это!). Я «предполагал», что использование JsonBuilder будет похоже на MarkupBuilder (я даже думал, что они оба происходят от BuilderSupport, упс). Еще раз спасибо, я снова в деле - и есть чему учиться! :)