2017-06-20 2 views
0

dieses JSON von einem API-Aufruf via curl bauen Jenkins genommen MitVerwenden jq spezifische Schlüssel greifen: Wert-Paar von n-te Objekt in einem JSON-Array

{ 
    "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun", 
    "actions" : [ 
     { 
      "_class" : "hudson.model.CauseAction", 
      "causes" : [ 
       { 
        "_class" : "jenkins.branch.BranchIndexingCause", 
        "shortDescription" : "Branch indexing" 
       } 
      ] 
     }, 
     { 
      "_class" : "hudson.model.ParametersAction", 
      "parameters" : [ "..." ] 
     }, 
     { 
      "_class" : "hudson.tasks.junit.TestResultAction", 
      "failCount" : 1, 
      "skipCount" : 14, 
      "totalCount" : 222, 
      "urlName" : "testReport" 
     } 
    ], 
    "artifacts" : [ "..." ], 
    "result" : "UNSTABLE", 
    "previousBuild" : { 
     "number" : 98, 
     "url" : "<some Url>" 
    } 
} 

Warum kann ich jq '{result}' <fileNameWithJSON> tun und bekommen

{ "result" : "UNSTABLE" } 

Aber ich kann jq '{.actions[2] failCount}' <fileNameWithJSON> oder andere Variationen nicht wie

  • jq '{actions[2].failCount}'
  • jq '{actions[2] failCount}'
  • jq '{actions .[2].failCount}'
  • usw.

    { "failCount" : "1" } zu bekommen?

Ich möchte die result sowie actions[2] failCount, actions[2] skipCount und actions[2] totalCount schnappen Sie sich einen neuen JSON wie diese zu erstellen:

{ "result" : "UNSTABLE","failCount" : 1, "skipCount" : 14,"totalCount" : 222} 

EDIT:

Mein Ziel war nicht müssen die Schlüssel erneut eingeben, falls sie in der API geändert wurden. Ich wollte das im Wesentlichen nicht:

Antwort

3

jq kann nur direkte Felder von einem Objekt zum anderen in Objektliteralen kopieren. Es wurde nicht programmiert, um tiefer als das zu gehen, obwohl es in anderen Sprachen, die diese Art von Feature unterstützen, durchaus möglich ist.

Wenn Ihr Ziel ist, die Wiederholung der Eigenschaftsnamen zu minimieren, müssen Sie nur den Filter ein wenig neu schreiben.

{result} + (.actions[2] | {failCount,skipCount,totalCount}) 
+0

Dies ist im Wesentlichen das nächste, was ich suche. Ich wollte die Schlüssel nicht noch einmal eingeben müssen: '{result, failCount": .actions [2] .failCount, "skipCount": .actions [2] .skipCount, "totalCount": .actions [2] .totalCount} '. Ich wollte einfach von der API selbst ziehen, so dass ich keine wichtigen Änderungen vornehmen müsste, wenn sich die API aus irgendeinem Grund ändert. Vielen Dank. – Wimateeka

0

{} Die Syntax ist Zucker. Es soll als Abkürzung verwendet werden, wenn Sie einen einfachen Ausdruck benötigen, aber es gibt keinen Grund, die gleiche verkürzte Syntax zu verwenden, wenn das, was Sie eigentlich wollen, interessanter ist.

jq ' 
    .actions[2] as $a2 |    # assign second action to a variable 
    { "result": .result,    # refer direct to original input when appropriate... 
    "skipCount": $a2.skipCount,  # ...or to that variable otherwise. 
    "failCount": $a2.failCount, 
    "totalCount": $a2.totalCount} 
' <<<"$json" 
0

Mein Ziel war nicht zu haben respezifizieren die Schlüssel, falls sie in der api geändert.

Wenn das eines der Hauptziele ist, mögen Sie vielleicht einen Ansatz durch die folgenden Beispiele betrachten, die auch keine Annahme macht, um das Element .actions die Informationen von Interesse enthält:

{ result } + (.actions[] | select(has("failCount"))) 

Mit Ihren Beispieldaten würde dies erzeugen:

{ 
    "result": "UNSTABLE", 
    "_class": "hudson.tasks.junit.TestResultAction", 
    "failCount": 1, 
    "skipCount": 14, 
    "totalCount": 222, 
    "urlName": "testReport" 
} 

Wenn Sie einige der zusätzlichen Felder nicht möchten, können Sie sie löschen, z Wenn Sie auf keinen Fall "_class" möchten, können Sie del(._class) zur Pipeline hinzufügen.

Verwandte Themen