jq - Objekte aus der Datei zum JSON-Array hinzufügen

9

Ich möchte mit jq ein Array mit Elementen und Wert in eine vorhandene JSON-Datei einfügen.

Ich habe bereits eine Datei (input.json) mit

{
  "id": 9,
  "version": 0,
  "lastUpdTs": 1532371267968,
  "name": "Training"
}

Ich möchte dies in ein anderes Gruppenarray in diesem json (orig.json) hinzufügen.

[
  {
    "name": "JAYS",
    "sourceConnection": {
      "name": "ORACLE_connection",
      "connectionType": "JDBC",
      "commProtocol": "JDBC"
    },
    "checked": true,
    "newlyAdded": false,
    "id": null,
    "groups": [],
    "displayName": "SCOTT",
    "defaultLevel": "MANAGED"
  }
]

Das Endergebnis sollte so aussehen

[
  {
    "name": "JAYS",
    "sourceConnection": {
      "name": "ORACLE_connection",
      "connectionType": "JDBC",
      "commProtocol": "JDBC"
    },
    "checked": true,
    "newlyAdded": false,
    "id": null,
    "groups": [
      {
        "id": 9,
        "version": 0,
        "lastUpdTs": 1532371267968,
        "name": "Training"
      }
    ],
    "displayName": "SCOTT",
    "defaultLevel": "MANAGED"
  }
]

Ich weiß, wie man einem Array Elemente hinzufügt, bin mir aber nicht sicher, wie ich aus einer Datei übergeben soll.

jq '.[].groups += [{"INPUT": "HERE"}]' ./orig.json
CLO
quelle

Antworten:

9

jqhat ein Flag zum Zuführen des tatsächlichen JSON-Inhalts mit seinem --argjsonFlag. Sie müssen lediglich den Inhalt der ersten JSON-Datei in einer Variablen im jqKontext speichern und im zweiten JSON aktualisieren

jq --argjson groupInfo "$(<input.json)" '.[].groups += [$groupInfo]' orig.json

Der Teil "$(<input.json)"ist ein Shell-Umleitungskonstrukt, um den Inhalt der angegebenen Datei auszugeben und mit dem Argument --argjsondafür in der Variablen zu speichern groupInfo. Jetzt fügen Sie es dem groupsArray im eigentlichen Filterteil hinzu.

Anders ausgedrückt ist die obige Lösung gleichbedeutend damit

jq --argjson groupInfo '{"id": 9,"version": 0,"lastUpdTs": 1532371267968,"name": "Training" }' \
   '.[].groups += [$groupInfo]' orig.json
Inian
quelle
1
Beachten Sie, dass dies $(<file)eine ksh / bash / zsh-Erweiterung ist und ansonsten nicht portabel ist. Sie könnten catstattdessen verwenden.
Michael Homer
8

Dies ist der genaue Fall, für den die inputFunktion bestimmt ist:

inputund Eingaben [...], die aus denselben Quellen (z. B. stdin, in der Befehlszeile genannte Dateien) wie jq selbst gelesen wurden. Diese beiden integrierten Funktionen und die eigenen Leseaktionen von jq können miteinander verschachtelt werden.

Das heißt, jqliest ein Objekt / einen Wert aus der Datei ein und führt die Pipeline darauf aus, und überall dort, wo es inputerscheint, wird die nächste Eingabe eingelesen und als Ergebnis der Funktion verwendet.

Das heißt, Sie können:

jq '.[].groups += [input]' orig.json input.json

mit genau dem Befehl, den Sie bereits geschrieben haben, plus inputals Wert. Der inputAusdruck wertet das (erste) Objekt aus, das aus der nächsten Datei in der Argumentliste gelesen wurde, in diesem Fall den gesamten Inhalt von input.json.

Wenn Sie mehrere Elemente einfügen müssen, können Sie diese inputsstattdessen mit derselben Bedeutung verwenden. Es wird über die Befehlszeile gleichermaßen auf eine oder mehrere Dateien angewendet und [inputs]repräsentiert alle Dateikörper als Array.

Es ist auch möglich, Dinge zu verschachteln, um mehrere origDateien mit jeweils einer eingefügten Begleitdatei zu verarbeiten , aber das Trennen der Ausgaben wäre mühsam.

Michael Homer
quelle
Aber damit kann ich wahrscheinlich keine Nicht-JSON-Dateien einbinden. Mit --argkann ich machen : jq --arg "$(<1.txt)" '{file: $file}'.
X-Yuri
Außerdem befindet sich die Datei möglicherweise nicht auf der Festplatte. Möglicherweise haben Sie die Datei aus dem Internet in eine Variable ( file=$(curl ...)) abgerufen . In diesem Fall gibt es wahrscheinlich keine Möglichkeit, die inputFunktion zu verwenden . <(echo "$file")funktioniert nicht
X-Yuri
@MichaelHomer wie, wenn wir vor dem Zusammenführen Änderungen in input.json vornehmen möchten?
ImranRazaKhan