JQ gibt JSON-Zeilen ohne Kommas zurück

JQ gibt JSON-Zeilen ohne Kommas zurück

Um es klar zu sagen: Ich möchte eine Pseudo-JSON-Ausgabe, die hier in eine andere statische JSON-Datei geschrieben wird, also nicht in ein Array oder so etwas verpackt, sondern einfach die fehlenden Kommas nach jeder Entität in meiner Ausgabe.

Derzeit lautet meine Abfrage:

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

Welche Ausgaben:

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

Dabei will ich eigentlich:

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

Beachten Sie das Komma nach jeder Entität! Es macht mich verrückt. Ich habe versucht, join(", ")an verschiedenen Stellen ein „ein“ hinzuzufügen, aber das hat entweder keine Auswirkungen auf die endgültige Ausgabe oder die Kompilierung schlägt fehl, je nachdem, wo ich es platziere.

Hier ist das JQPlay mit enthaltenen Datenhttps://jqplay.org/s/xx3F_IWn03g


Ursprüngliche JSON-Eingabe:

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

Antwort1

Sie scheinen zu wollenänderndie Einträge, die auditIdauf die Zeichenfolge gesetzt sind categories. Was Sie tun, ist,Extraktdiese Elemente aus dem Array der obersten Ebene und ändern Sie sie. Dadurch erhalten Sie eine Menge (kein Array) von Objekten.

Anstatt |Elemente aus dem Array zu extrahieren, verwenden Sie|=um seine Elemente zu ändern. Am Ende dieser Antwort erfahren Sie, wie Sie das resultierende Array ordnungsgemäß in eine JSON-Struktur in einer anderen Datei einfügen.

Verwenden Sie also

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

.[]Alternativ können Sie es auch ganz weglassen und stattdessenmap()mit dem Ausdruck für jedes der Elemente im Array der obersten Ebene:

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

Diese Ausdrücke ergeben ein Array von Elementen wie dieses:

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

Um dieses Array zu einem bereits vorhandenen Array in einer anderen Datei hinzuzufügen, können Sie Folgendes tun (vorausgesetzt, es gibt einen arraySchlüssel auf der obersten Ebene von otherfileund Ihre Eingabe befindet sich in inputfile; der Schlüssel wird erstellt, wenn er noch nicht vorhanden ist):

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

Bei inputder Ausführung wird das Array aus der zweiten Datei in der Befehlszeile gelesen.

Ändern Sie +=den Wert in „Nur“ =, wenn Sie den Wert des vorhandenen Schlüssels ersetzen arrayund nicht hinzufügen möchten.

Antwort2

Ja, das ist es, was der []Iterator macht, Sie erhalten für jeden eine JSON-Datei. Um ein Array zu erhalten, können Sie den gesamten Ausdruck einschließen, um [...]daraus ein Array zu machen, oder verwenden, map()um das Eingabearray an Ort und Stelle zu ändern, anstatt []über seine Elemente zu iterieren.

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

Wenn Sie durch Kommas getrennte Elemente ohne das umschließende verwenden [, ]um daraus ein Array zu machen, wäre das JSON ungültig. Falls Sie das jedoch möchten, können Sie es per Pipe an weiterleiten, sed '1d;$d'um die erste und die letzte Zeile zu löschen.

verwandte Informationen