JQ retorna linhas json sem vírgulas

JQ retorna linhas json sem vírgulas

Para ser claro - eu quero uma saída pseudo-JSON que será escrita em outro arquivo JSON estático aqui ... portanto, não agrupada em uma matriz ou algo assim, simplesmente obtendo as vírgulas ausentes após cada entidade em minha saída.

Atualmente minha consulta é:

.[] | select(.auditId == "categories") |
{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
  }
}

Quais saídas:

{
  "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)"
  }
}

Quando na verdade eu quero:

{
  "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)"
  }
},

Observe a vírgula após cada entidade! Isso está me deixando maluco, tentei adicionar um join(", ")em vários lugares, mas isso não faz nada na saída final ou não consegue compilar dependendo de onde eu o coloco.

Aqui está o jqplay com dados incluídoshttps://jqplay.org/s/xx3F_IWn03g


JSON de entrada original:

[
  {
    "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"
  }
]

Responder1

Você parece querermodificaras entradas que foram auditIddefinidas para a string categories. O que você está fazendo éextrairesses elementos da matriz de nível superior e modificá-los. Isso fornece um conjunto (não uma matriz) de objetos.

Em vez de usar |para extrair elementos do array, use|=modificar seus elementos. Veja o final desta resposta para saber como inserir corretamente o array resultante em uma estrutura JSON em outro arquivo.

Então, use

.[] |= (
    select(.auditId == "categories") |
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
        }
    }
)

Como alternativa, não use .[]nada e, em vez disso, usemap()com a expressão em cada um dos elementos da matriz de nível superior:

map(
    select(.auditId == "categories") |
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
        }
    }
)

Essas expressões fornecerão uma série de elementos como este:

[
  {
    "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)"
    }
  }
]

Para adicionar esse array a um array já existente em outro arquivo, você pode fazer isso (assumindo que existe uma arraychave no nível superior otherfilee que sua entrada está em inputfile; a chave será criada se ainda não existir):

jq '.array += ( input |
    map(
        select(.auditId == "categories") |
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*\(.auditProperty):* \(.actual) (expected \(.expected))"
            }
        }
    )
)' otherfile inputfile

Quando inputé executado, o array do segundo arquivo na linha de comando é lido.

Mude +=para apenas =se desejar substituir o arrayvalor da chave existente em vez de adicioná-lo.

Responder2

Sim, é isso que o []iterador faz, você obtém um arquivo JSON para cada um. Para obter uma matriz, você pode incluir a expressão inteira para [...]criar uma matriz a partir dela ou usá-la map()para modificar a matriz de entrada no local, em vez de []iterar sobre seus elementos.

$ 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
]

Ter elementos separados por vírgula sem o fechamento [, ]para torná-lo um array tornaria o json inválido, mas se é isso que você deseja, você pode canalizá-lo sed '1d;$d'para excluir a primeira e a última linhas.

informação relacionada