2016-03-29 12 views
2

Ich habe eine JSON-Datei, die wie folgt aussieht (ein grobes Schema):jq: select ohne Elemente aus Array fallen

[{ 
    "custom_variables": [ 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "profile_id", 
      "value": "123" 
     } 
    ], 
    // many fields 
    "xxx": "xxx", 
    "xxx": "xxx", 
    "xxx": "xxx" 
}] 

Ich bin mit jq alle Felder von der obersten Ebene Objekt zu extrahieren. Das Feld custom_variables enthält ein Array von Objekten mit Namen und Wert.

Ich möchte ein bestimmtes Objekt aus custom_variables mit seinem Namen extrahieren.

Also, was ich tue, ist dies:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") 
    } 
)' 

Es ist fast funktioniert; Sie ruft die gewünschte Variable ab, wenn sie existiert, aber wenn dies nicht der Fall ist (oder wenn custom_variables nicht selbst vorhanden ist), wird das gesamte Objekt der obersten Ebene gelöscht. Am Ende bekomme ich weniger Objekte, als ich in das Skript einfüge.

Wie kann ich nur null zurückgeben, wenn ich dieses Feld nicht finde, aber den Rest der Daten behalten?

Antwort

0

Das funktioniert, aber es sieht hässlich aus. Irgendwelche besseren Lösungen?

custom_variables: (if (.custom_variables | length > 0) 
      then (.custom_variables | .[]? | select(.name == "variable_name") | .value | scan("\\d+")) 
      else null 
      end) 
1

Verwenden des alternativen Operator (//) einen Strom von Null-Elementen (wie beispielsweise solche, die durch select oder .[] erzeugt werden kann) zu transformieren, in einen Wert:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") // null 
    } 
)' 

Dies wird .xxx sein null, wenn auf der linken Seite von // ein Null-Element-Stream vorhanden ist.

Sie können natürlich, legen Sie die alternativen Betreiber an einer anderen Stelle des Nullelement Strom zu einem früheren oder späteren Zeitpunkt, wie auf der Objektebene zu erfassen:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") 
    } // {} 
)' 
0

Die folgende tut, was Sie haben angegeben, dass Sie möchten, so gut ich Ihre Anforderungen verstehe.

map(if .custom_variables 
    then .custom_variables |= (map(select(.name == "variable_name") | .value) 
           | .[0]) 
    else . 
    end) 

Beispiel Eingabe:

[{ 
    "custom_variables": [ 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "variable_name", 
      "value": "123" 
     } 
    ], 
    "xxx1": "xxx", 
    "xxx2": "xxx", 
    "xxx3": "xxx" 
}, 

{ 
    "yyy1": "yyy", 
    "yyy2": "yyy", 
    "yyy3": "yyy" 
} 
] 

Output:

[ 
    { 
    "custom_variables": "123", 
    "xxx1": "xxx", 
    "xxx2": "xxx", 
    "xxx3": "xxx" 
    }, 
    { 
    "yyy1": "yyy", 
    "yyy2": "yyy", 
    "yyy3": "yyy" 
    } 
]