2014-02-12 75 views
5

我想教自己ruby并解决工作中的问题。我的最终目标是从API中提取出JSON响应中的许多字段中的三个,并将其操纵并转储为CSV以用于执行报告。ruby​​:从嵌套json中提取字段

的JSON的结构是:

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

具体地说我想提取出dataPointstartOnackedOn

我想我需要首先提取总价值,所以我知道我有多少警报。这将帮助我循环通过警报实例。

*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* 

我被困在试图提取出总数。输出不显示任何内容:

sudo ruby alerts.rb 
[] 

有没有更好的方法来做到这一点?

回答

10

试试这个:

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

对于刚刚总:

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

对于其他值,你问:

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

现在的问题是,你想要什么与结果做什么?你想收集他们到一个新的哈希? json['data']['alerts']是一个数组,因此您必须决定如何收集它们。你可以这样做:

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 

现在你可以在collected_alerts

+0

所有这些值添加此测试 jsonResponse = JSON.parse(响应) 总= jsonResponse [ '数据'] [ '总' ] pp总计 并且得到以下错误: sudo ruby​​ alerts.rb /usr/local/lib/ruby/2.1.0/json/common.rb:155:in'initialize':没有隐式转换的Net :: HTTPOK到String(TypeError) \t from /usr/local/lib/ruby/2.1.0/json/common.rb:155:i ñ'新从alerts.rb \t '从/usr/local/lib/ruby/2.1.0/json/common.rb:155:in'解析 \t':37:在'

“ 我最终要在将数值加载到散列或数组中以进行操作之后,将其放入csv 谢谢! – achan

+0

让它成为JSON.parse(response.body) – DiegoSalazar

+0

我还有两个问题,然后我完成了。 #计算确认警报并将它存储在timeToAcks #分钟是确认时间 - 开始时间,这将使我们秒/ 60分钟。 timeToAck =(警报[ 'ackedOn'] - 警报[ 'startOns'])/ 60 collected_alerts [ 'timeToAcks'] << timeToAck 当我运行它我得到这个错误 alerts.rb:57:在' - ':nil不能从alerts.rb强制插入到Fixnum(TypeError)中:57:在'block中

'中来自alerts.rb:47:在'each'中来自警报。rb:47:在'
' – achan