JQ возвращает строки JSON без запятых

JQ возвращает строки JSON без запятых

Для ясности — мне нужен вывод псевдо-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'чтобы удалить первую и последнюю строки.

Связанный контент