
Для ясности — мне нужен вывод псевдо-JSON, который будет записан в другой статический файл JSON... поэтому не оборачиваю его в массив или что-то в этом роде, а просто добавляю недостающие запятые после каждой сущности в выводе.
На данный момент мой запрос:
.[] | select(.auditId == "categories") |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
}
}
Какие выходы:
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*performance:* 1 (expected 0.8)"
}
}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*accessibility:* 1 (expected 0.9)"
}
}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*best-practices:* 0.96 (expected 0.9)"
}
}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*seo:* 0.64 (expected 0.5)"
}
}
Когда на самом деле я хочу:
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*performance:* 1 (expected 0.8)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*accessibility:* 1 (expected 0.9)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*best-practices:* 0.96 (expected 0.9)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*seo:* 0.64 (expected 0.5)"
}
},
Обратите внимание на запятую после каждой сущности! Это сводит меня с ума, я пробовал добавлять join(", ")
в разных местах, но это либо ничего не меняет в конечном выводе, либо не компилируется в зависимости от того, куда я его помещаю.
Вот jqplay с включенными даннымиhttps://jqplay.org/s/xx3F_IWn03g
Исходный входной JSON:
[
{
"name": "minScore",
"expected": 0.8,
"actual": 1,
"values": [
1,
1,
1
],
"operator": ">=",
"passed": true,
"auditProperty": "performance",
"auditId": "categories",
"level": "error",
"url": "http://localhost:8080/page2"
},
{
"name": "minScore",
"expected": 0.9,
"actual": 1,
"values": [
1,
1,
1
],
"operator": ">=",
"passed": true,
"auditProperty": "accessibility",
"auditId": "categories",
"level": "error",
"url": "http://localhost:8080/page2"
},
{
"name": "minScore",
"expected": 0.9,
"actual": 0.96,
"values": [
0.93,
0.96,
0.96
],
"operator": ">=",
"passed": true,
"auditProperty": "best-practices",
"auditId": "categories",
"level": "error",
"url": "http://localhost:8080/page2"
},
{
"name": "minScore",
"expected": 0.5,
"actual": 0.64,
"values": [
0.64,
0.64,
0.64
],
"operator": ">=",
"passed": true,
"auditProperty": "seo",
"auditId": "categories",
"level": "error",
"url": "http://localhost:8080/page2"
}
]
решение1
Кажется, ты хочешьизменитьзаписи, которые auditId
установили строку categories
. То, что вы делаете, этоизвлекатьэти элементы из массива верхнего уровня и модифицируйте их. Это дает вам набор (не массив) объектов.
Вместо использования |
для извлечения элементов из массива используйте|=
для изменения его элементов. Смотрите конец этого ответа, чтобы узнать, как правильно вставить полученный массив в структуру JSON в другом файле.
Итак, используйте
.[] |= (
select(.auditId == "categories") |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
}
}
)
В качестве альтернативы, не используйте .[]
вообще, а вместо этого используйтеmap()
с выражением для каждого из элементов в массиве верхнего уровня:
map(
select(.auditId == "categories") |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
}
}
)
Эти выражения дадут вам массив элементов вроде этого:
[
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*performance:* 1 (expected 0.8)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*accessibility:* 1 (expected 0.9)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*best-practices:* 0.96 (expected 0.9)"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*seo:* 0.64 (expected 0.5)"
}
}
]
array
Чтобы добавить этот массив к уже существующему массиву в другом файле, вы можете сделать это (предполагая , что на верхнем уровне есть ключ otherfile
и что ваши входные данные находятся в inputfile
; ключ будет создан, если он еще не существует):
jq '.array += ( input |
map(
select(.auditId == "categories") |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
}
}
)
)' otherfile inputfile
При input
выполнении считывается массив из второго файла в командной строке.
Измените +=
на just, =
если вы хотите заменить существующее array
значение ключа, а не добавлять к нему.
решение2
Да, это то, что []
делает итератор, вы получаете один файл JSON для каждого. Чтобы получить массив, вы можете заключить все выражение в , [...]
чтобы сделать из него массив, или использовать map()
для изменения входного массива на месте вместо []
итерации по его элементам.
$ echo '[1,2,3,4]' | jq '.[]|select(.<3)'
1
2
$ echo '[1,2,3,4]' | jq '[.[]|select(.<3)]'
[
1,
2
]
$ echo '[1,2,3,4]' | jq 'map(select(.<3))'
[
1,
2
]
Если элементы разделены запятыми без заключительных скобок [
, ]
то преобразование их в массив сделает его недействительным json, но если это то, что вам нужно, вы можете передать его по конвейеру , sed '1d;$d'
чтобы удалить первую и последнюю строки.