2016-06-08 35 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?'函数就会赢得没有工作。 –