20

I'm using a Ruby script to interface with an application API and the results being returned are in a JSON format. For example:

{
  "incidents": [
    {
      "number": 1,
      "status": "open",
      "key": "abc123"
    }
    {
      "number": 2,
      "status": "open",
      "key": "xyz098"
    }
    {
      "number": 3,
      "status": "closed",
      "key": "lmn456"
    }
  ]
}

I'm looking to search each block for a particular "key" value (yzx098 in this example) and return the associated "number" value.

Now, I'm very new to Ruby and I'm not sure if there's already a function to help accomplish this. However, a couple days of scouring the Googles and Ruby resource books hasn't yielded anything that works.

Any suggestions?

2
  • Are you looking for the JSON module of the standard library? Commented Mar 14, 2014 at 21:02
  • 1
    The hashes need commas between them to be valid parsable json. I tried to edit the Q, but you need to change 6 characters - can't add 2 commas :) Commented Mar 14, 2014 at 21:25

2 Answers 2

46

First of all, the JSON should be as below: (note the commas)

 {
  "incidents": [
    {
      "number": 1,
      "status": "open",
      "key": "abc123"
    },
    {
      "number": 2,
      "status": "open",
      "key": "xyz098"
    },
    {
      "number": 3,
      "status": "closed",
      "key": "lmn456"
    }
  ]
}

Strore the above json in a variable

s =  '{"incidents": [{"number": 1,"status": "open","key": "abc123"},{"number": 2,"status": "open","key": "xyz098"},{"number": 3,"status": "closed","key": "lmn456"}]}'

Parse the JSON

h = JSON.parse(s)

Find the required number using map

h["incidents"].map {|h1| h1['number'] if h1['key']=='xyz098'}.compact.first

Or you could also use find as below

 h["incidents"].find {|h1| h1['key']=='xyz098'}['number']

Or you could also use select as below

h["incidents"].select {|h1| h1['key']=='xyz098'}.first['number']
Sign up to request clarification or add additional context in comments.

2 Comments

don't need if.... select or find throws the selection, whenever block returns true. Only h1['key']=='xyz098' is enough.
Thanks for the help! Pointed me in the right direction and I was able to get this sorted out. Cheers!
4

Do as below

# to get numbers from `'key'`.
json_hash["incidents"].map { |h| h['key'][/\d+/].to_i }
  • json_hash["incidents"] - will give you the value of the key "incidents", which is nothing but an array of hash.

  • map to iterate thorough each hash and collect the value of 'key'. Then applying Hash#[] to each inner hash of the array, to get the value of "key". Then calling str[regexp], to get only the number strings like '098' from "xyz098", finally applying to_i to get the actual integer from it.

If the given hash actually a json string, then first parse it using JSON::parse to convert it to a hash.Then do iterate as I said above.

require 'json'

json_hash = JSON.parse(json_string)
# to get values from the key `"number"`.
json_hash["incidents"].map { |h| h['number'] } # => [1, 2, 3]
# to search and get all the numbers for a particular key match and take the first
json_hash["incidents"].select { |h| h['key'] == 'abc123' }.first['number'] # => 1
# or to search and get only the first number for a particular key match
json_hash["incidents"].find { |h| h['key'] == 'abc123' }['number'] # => 1

1 Comment

I believe he was asking for the "number" field of the hash with key "xyz098" This could be done using something like json_hash["incidents"].select { |h| h['key'] == 'abc123' }.first['number'] which gives you 2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.