2016-06-08 32 views
0

我是新來的紅寶石,請原諒我可能承受的任何無知。我想知道如何解析屬於特定鍵的每個值的JSON響應。響應的格式爲,Ruby,解析一個值爲數組的JSON響應

[ 
    { 
    "id": 10008, 
    "name": "vpop-fms-inventory-ws-client", 
    "msr": [ 
     { 
     "key": "blocker_violations", 
     "val": 0, 
     "frmt_val": "0" 
     }, 
    ] 
    }, 
    { 
    "id": 10422, 
    "name": "websample Maven Webapp", 
    "msr": [ 
     { 
     "key": "blocker_violations", 
     "val": 0, 
     "frmt_val": "0" 
     }... 

有一個在響應一些其他項目,但沒有一個代碼塊巨大的緣故,我已經縮短了後援代碼,我寫的是:

require 'uri' 
require 'net/http' 
require 'JSON' 
url = URI({my url}) 

    http = Net::HTTP.new(url.host, url.port) 

    request = Net::HTTP::Get.new(url) 
    request["cache-control"] = 'no-cache' 
    request["postman-token"] = '69430784-307c-ea1f-a488-a96cdc39e504' 

    response = http.request(request) 
    parsed = response.read_body 

    h = JSON.parse(parsed) 

    num = h["msr"].find {|h1| h1['key']=='blocker_violations'}['val'] 

我基本上是尋找每個阻滯劑違規的val(json響應包含數百個條目,所以我期待數百個阻滯劑值)。我希望num會包含所有'val'的數組。如果您對此有所瞭解,這將非常有幫助!

編輯!我得到一個控制檯輸出

scheduler caught exception: 
no implicit conversion of String into Integer 
C:/dashing/test_board/jobs/issue_types.rb:20:in `[]' 
C:/dashing/test_board/jobs/issue_types.rb:20:in `block (2 levels) in <top (requi 
red)>' 
C:/dashing/test_board/jobs/issue_types.rb:20:in `select' 

我懷疑這可能有太多的問題,但一些幫助表示讚賞!

+0

您需要遍歷對象的數組過來,然後遍歷msr'的'數組,尋找每個「鍵」匹配。 –

回答

1

你需要做2件事。首先,你被返回一個數組,你只對一個元素的子集感興趣。這是通過過濾器解決的常見模式,或者Ruby中的select。其次,您希望選擇這些元素的條件也取決於另一個數組的值,您需要使用不同的技術進行過濾。你可以嘗試這樣的:

res = [ 
    { 
    "id": 10008, 
    "name": "vpop-fms-inventory-ws-client", 
    "msr": [ 
     { 
     "key": "blocker_violations", 
     "val": 123, 
     "frmt_val": "0" 
     } 
    ] 
    }, 
    { 
    "id": 10008, 
    "name": "vpop-fms-inventory-ws-client", 
    "msr": [ 
     { 
     "key": "safe", 
     "val": 0, 
     "frmt_val": "0" 
     } 
    ] 
    } 
] 

# define a lambda function that we will use later on to filter out the blocker violations 
violation = -> (h) { h[:key] == 'blocker_violations' } 

# Select only those objects who contain any msr with a key of  blocker_violations 
violations = res.select {|h1| h1[:msr].any? &violation } 

# Which msr value should we take? Here I just take the first. 
values = violations.map {|v| v[:msr].first[:val] } 

你可能有這段代碼的問題是,msr是一個數組。因此從理論上講,最終可能會有msr中的兩個對象,一個是阻止者違規,另一個不是。你必須決定如何處理。在我的示例中,如果它通過使用any?而導致單個攔截器違規,我將它包括在內。但是,如果所有msr對象都受到阻止,您可能只希望包含它們。您可以通過all?方法執行此操作。

然後你面對的第二個問題是,要返回哪個值?如果msr對象中存在多個阻止程序違例,您選擇哪個值?我只是採取了first之一 - 但這可能不適合你。

根據您的要求,我的示例可能工作,或者您可能需要適應它。

另外,如果你從來沒有遇到過的lambda語法之前,你可以閱讀更多關於它here

+0

不建議您的建議是錯誤的,但我認爲我有另一個錯誤,阻止我檢查這種方式是否有效。希望我能回到這個。 –

+0

不,你說得對。我的答案不會工作,因爲'msr'是一個數組,而不是一個散列。我會更新一個更好的答案。 – MrWillihog

+0

是的!這正是我需要的,通過一些調整來解決這個問題。非常感謝!只需跟進一下,我該如何讓res = h'或其他'res ='這樣res是一個包含整個api調用而不是一個字符串(?)的數組,否則'any?'函數就會贏得沒有工作。 –