Alex Smolov
Alex Smolov

Reputation: 1861

Parse JSON with an array in Rails

I have the following JSON string returned by a remote server:

{
  "users": [
    {
      "user_id": 1,
      "name": "Chris Rivers",
    },
    {
      "user_id": 3,
      "name": "Peter Curley",
    }
  ]
}

I'd like to iterate the users.

ActiveSupport::JSON.decode(response.body)["users"].each do |user|
    puts user["name"]
end

As far as I understand, the problem is: ruby doesn't recognize ActiveSupport::JSON.decode(response.body)["users"] as an array, and thus puts returns me only the first user.

How do I solve that problem?

Upvotes: 6

Views: 14079

Answers (3)

Dave Newton
Dave Newton

Reputation: 160170

The problem isn't not recognizing the array, it's the trailing commas after the "name" elements.

Removing those allows JSON parsing to proceed normally:

pry(main)> ActiveSupport::JSON.decode(s)["users"]
=> [{"user_id" => 1, "name" => "Chris Rivers"},
    {"user_id" => 3, "name" => "Peter Curley"}]

Upvotes: 6

Dan Wich
Dan Wich

Reputation: 4943

Does your source data actually have the trailing commas after each user's name? I get a parse error for that, but your code works as you want it to if I remove them:

json = '{ "users": [ { "user_id": 1, "name": "Chris Rivers" }, { "user_id": 3, "name": "Peter Curley" } ]}'
ActiveSupport::JSON.decode(json)["users"].each do |user|
   puts user["name"]
end

Upvotes: 8

deefour
deefour

Reputation: 35350

What you have pasted is not valid JSON. The trailing comma after on each "name" is a problem

"name": "Chris Rivers",

You'll get a LoadError trying to decode this with ActiveSupport::JSON.decode

MultiJson::LoadError: 399: unexpected token at '{"user_id": 1,"name": "Chris Rivers",},{"user_id": 3,"name": "Peter Curley",}]}'

If we clean up the JSON, turning it into something ActiveSupport::JSON.decode can understand

"{\"users\": [{\"user_id\": 1,\"name\": \"Chris Rivers\"},{\"user_id\": 3,\"name\": \"Peter Curley\"}]}"

you'll see there is no issue iterating over each object in "users" (x below is the above JSON string)

[8] pry(main)> ActiveSupport::JSON.decode(x)["users"].map { |user| user["name"] }
=> ["Chris Rivers", "Peter Curley"]

Upvotes: 10

Related Questions