JeuelyFish JeuelyFish - 3 months ago 10
Ruby Question

Ruby: How to find nested object that matches certain attributes

My ruby is quite rusty and I'm having a hard time parsing through some JSON that I'm getting back from an HTTParty call in ruby. Currently, I am trying to get the 'ladderId' properties value that is deeply nested in a parsed JSON response.

response = HTTParty.get('myApiUrlHere')
json = JSON.parse(response.body)

ladder_id = ## // find within the "CurrentSeason" object a "ladder"
## // object whose "league" property has the value
## // "GRANDMASTER", and return that objects ladder ID


If my wording is confusing, I should expect the value "197606" when given the following JSON return

{
"currentSeason": [{
"ladder": [{
"ladderName": "Alzadar Theta",
"ladderId": 197606,
"division": 5,
"rank": 65,
"league": "DIAMOND",
"matchMakingQueue": "LOTV_TWOS",
"wins": 8,
"losses": 2,
"showcase": true
}],
"characters": [{
"id": 989277,
"realm": 1,
"displayName": "Warren",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/989277/1/Warren/"
}, {
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": []
}, {
"ladder": [{
"ladderName": "Kerrigan Kilo",
"ladderId": 197160,
"division": 1,
"rank": 95,
"league": "MASTER",
"matchMakingQueue": "LOTV_TWOS_COMP",
"wins": 1,
"losses": 0,
"showcase": true
}],
"characters": [{
"id": 3650249,
"realm": 1,
"displayName": "CranK",
"clanName": "Axiom eSports",
"clanTag": "Ax",
"profilePath": "/profile/3650249/1/CranK/"
}, {
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": []
}, {
"ladder": [],
"characters": [{
"id": 2238820,
"realm": 1,
"displayName": "Sugar",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/2238820/1/Sugar/"
}, {
"id": 2481800,
"realm": 1,
"displayName": "starkiller",
"clanName": "Ørdo Equitum",
"clanTag": "ØE",
"profilePath": "/profile/2481800/1/starkiller/"
}, {
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": [{
"mmq": "LOTV_THREES",
"gamesPlayed": 2
}]
}, {
"ladder": [{
"ladderName": "Carrier Zeta",
"ladderId": 197921,
"division": 1,
"rank": 1,
"league": "GRANDMASTER",
"matchMakingQueue": "LOTV_SOLO",
"wins": 187,
"losses": 51,
"showcase": true
}],
"characters": [{
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": []
}],
"previousSeason": [{
"ladder": [{
"ladderName": "Marine Foxtrot",
"ladderId": 196150,
"division": 1,
"rank": 35,
"league": "MASTER",
"matchMakingQueue": "LOTV_TWOS_COMP",
"wins": 4,
"losses": 5,
"showcase": false
}, {
"ladderName": "War Pigs Foxtrot",
"ladderId": 196853,
"division": 11,
"rank": 73,
"league": "DIAMOND",
"matchMakingQueue": "LOTV_TWOS",
"wins": 2,
"losses": 0,
"showcase": false
}],
"characters": [{
"id": 3650249,
"realm": 1,
"displayName": "CranK",
"clanName": "Axiom eSports",
"clanTag": "Ax",
"profilePath": "/profile/3650249/1/CranK/"
}, {
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": []
}, {
"ladder": [{
"ladderName": "Mutalisk Echo",
"ladderId": 196647,
"division": 1,
"rank": 3,
"league": "GRANDMASTER",
"matchMakingQueue": "LOTV_SOLO",
"wins": 134,
"losses": 38,
"showcase": false
}],
"characters": [{
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": []
}, {
"ladder": [],
"characters": [{
"id": 2238820,
"realm": 1,
"displayName": "Sugar",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/2238820/1/Sugar/"
}, {
"id": 5220949,
"realm": 1,
"displayName": "True",
"clanName": "PSISTORM Gaming",
"clanTag": "PSISTM",
"profilePath": "/profile/5220949/1/True/"
}],
"nonRanked": [{
"mmq": "LOTV_TWOS_COMP",
"gamesPlayed": 2
}]
}]
}

Answer

Its pretty weird JSON, following code should work for your requirement:

obj = JSON.parse('your json string')
desired_obj = obj["currentSeason"].select do |i| 
     !i["ladder"][0].nil? && 
     i["ladder"][0]['league'] == 'GRANDMASTER'
end

ladder_id = desired_obj[0]['ladder'][0]['ladderId']
#=> 197921