2014-02-12 16 views
5

Ich versuche, mich selbst Rubin zu lehren und ein Problem bei der Arbeit zu lösen. Mein oberstes Ziel ist es, drei der vielen Felder in der JSON-Antwort von einer API herauszuholen, zu manipulieren und in CSV für Executive-Berichte zu speichern.Ruby: Extrahieren von Feldern aus verschachtelten JSON

Die Struktur des JSON ist:

{ 
    "status": 200, 
    "data": { 
    "total": 251, 
    "alerts": [ 
     { 
     "dataPoint": "x", 
     "ackedBy": "x", 
     "dataSourceInstance": "x", 
     "dataSource": "x", 
     "host": "x", 
     "endOn": 0, 
     "ackedOn": 1385085190, 
     "dataSourceInstanceId": 588384, 
     "hostId": 935, 
     "type": "alert", 
     "dataSourceId": 694, 
     "ackedOnLocal": "2013-11-21 17:53:10 PST", 
     "id": 6170384, 
     "startOn": 1385084917, 
     "thresholds": "!= 1 1 1", 
     "endOnLocal": "", 
     "level": "error", 
     "ackComment": "x", 
     "value": "No Data", 
     "hostDataSourceId": 211986, 
     "acked": true, 
     "hostGroups": [{ 
      "alertEnable": true, 
      "createdOn": 1362084592, 
      "id": 21, 
      "parentId": 78, 
      "description": "", 
      "appliesTo": "", 
      "name": "2600hz", 
      "fullPath": "x" 
     }], 
     "startOnLocal": "2013-11-21 17:48:37 PST" 
     }, 

genauer zu sein Ich möchte dataPoint extrahieren, startOn, ackedOn.

Ich denke, ich muss zuerst den Gesamtwert extrahieren, damit ich weiß, wie viele Warnungen ich habe. Das wird mir helfen, die Alertinstanzen zu durchlaufen.

*url = "https://xyz" 
uri = URI(url) 
http = Net::HTTP.new(uri.host, 443) 
http.use_ssl = true 
http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
req = Net::HTTP::Get.new(uri.request_uri) 
response = http.request(req) 

# Make sure we had a proper web response 
if response.code == '200' then 

# Set up that the total is two levels deep in the json 
path = JsonPath.new('$.total') 

# Extract out total field into variable 
totalAlerts = path.on(response) 

# Print hash to confirm value 
pp totalAlerts 

end* 

Ich stecke fest, versuchen, nur die Summe herauszuziehen. Ausgabe zeigt nichts:

sudo ruby alerts.rb 
[] 

Gibt es einen besseren Weg, dies zu tun?

Antwort

10

Try this:

# just for demonstration, you would probably do json = JSON.parse(response) 
json = { 
    "status": 200, 
    "data": { 
    "total": 251, 
    "alerts": [ 
     { 
     "dataPoint": "x", 
     "ackedBy": "x", 
     ... 

Für nur die Gesamt:

total = json['data']['total'] 

Für die anderen Werte gefragt Sie:

json['data']['alerts'].each do |alerts| 
    # do whatever you want with these... 
    alerts['dataPoint'] 
    alerts['startOn'] 
    alerts['ackedOn'] 

Nun ist die Frage, was wollen Sie mit den Ergebnissen zu tun haben? Möchten Sie sie in einem neuen Hash sammeln? Die json['data']['alerts'] ist ein Array, so dass Sie entscheiden müssen, wie Sie sie sammeln möchten. Sie tun können:

collected_alerts = { 'dataPoints' => [], 'startOns' => [], 'ackedOns' => [] } 
json['data']['alerts'].each do |alerts| 
    collected_alerts['dataPoints'] << alerts['dataPoint'] 
    collected_alerts['startOns'] << alerts['startOn'] 
    collected_alerts['ackedOns'] << alerts['ackedOn'] 
end 

Jetzt können Sie alle diese Werte erhalten in collected_alerts

+0

ich diese zu testen hinzugefügt jsonResponse = JSON.parse (Antwort) gesamt = jsonResponse [ 'data'] [ 'total' ] pp Gesamt und die folgende Fehlermeldung erhalten: sudo ruby ​​alerts.rb /usr/local/lib/ruby/2.1.0/json/common.rb:155:in 'initialisieren ': keine implizite Konvertierung von Net :: HTTPOK in String (TypeError) \t von /usr/local/lib/ruby/2.1.0/json/common.rb:155:i n 'neue ' \t von /usr/local/lib/ruby/2.1.0/json/common.rb:155:in' Parse' \t von alerts.rb: 37: in '

' ich schließlich wollen um die Werte in Hash oder Array zu manipulieren, bevor Sie es in eine CSV setzen Dank! – achan

+0

mach es JSON.parse (response.body) – DiegoSalazar

+0

Ich habe zwei weitere Probleme und dann bin ich fertig. # Berechnen Sie Minuten, die es dauerte, um Alarm zu bestätigen und es in timeToAcks zu speichern # Formel ist Ack time - Startzeit, die uns Sekunden/60 geben würde, um Minuten zu geben. timeToAck = (Alerts [ 'ackedOn'] - Benachrichtigung [ 'startOns'])/60 collected_alerts [ 'timeToAcks'] << timeToAck Wenn ich es laufen bekomme ich diese Fehler alerts.rb: 57: in '- ': nil kann nicht in Fixnum (TypeError) von alerts.rb: 57: in' block in

'von alerts.rb: 47: in 'each' von Alerts eingezwängt werden.rb: 47: in '
' – achan

Verwandte Themen