我是红宝石的新手所以请原谅我可能承受的任何无知。我想知道如何解析属于特定键的每个值的JSON响应。响应的格式为
def "domestic rules"(from, to, oneWay, check) {
expect:
String mealResponse = getMealResponse(new BookingOptions.BookingOptionsBuilder().setFrom(from).setTo(to).setOneWay(oneWay).build());
check(mealResponse)
where:
from | to | oneWay || check
'MNL' | 'PEK' | true || assertNoMeals()
}
def assertNoMeals = {
assert JsonAssert.with(it)
.assertThat('$.links', hasSize(1))
.assertThat('$.links[0].rel', is("http://localhost:9001/api/docs/rels/ink/meal-allocations"))
.assertThat('$.links[0].uri', startsWith("http://localhost:9001/api/tenants/acme/meals/allocations/"));
}
响应中还有其他一些条目,但为了没有大量的代码,我已经缩短了它。我写的代码是:
[
{
"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"
}...
我基本上在寻找每个阻止程序违规的val(json响应包含数百个条目,所以我期待数百个阻止值)。我曾希望num会包含所有&val; s的数组。如果您对此有任何见解,那将会有很大的帮助!
EDIT!我正在获得
的控制台输出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']
我怀疑这个问题可能有太多关系,但是有些帮助表示赞赏!
答案 0 :(得分:1)
你需要做两件事。首先,您将返回一个数组,并且您只对元素的子集感兴趣。这是一个通过过滤器解决的常见模式,或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
中的2个对象,一个是阻塞者违规,另一个不是。你必须决定如何处理它。在我的示例中,如果通过any?
使用单个阻止程序,则将其包含在内。但是,如果所有msr
个对象都是阻止程序违规,您可能只希望包含它们。您可以通过all?
方法执行此操作。
您接下来面临的第二个问题是,要返回哪个值?如果msr
对象中存在多个阻止程序违规,您选择哪个值?我只拿了first一个 - 但这可能不适合你。
根据您的要求,我的示例可能有用,或者您可能需要对其进行调整。
此外,如果您以前从未遇到过lambda语法,可以阅读更多相关信息here