Undistraction
Undistraction

Reputation: 43402

Searching for attributes of name in a JSON decoded hash

I have a JSON file consisting of an array of galleries, each of which has its own array of photographs:

[
  {
    "title":"Some Title",
    "photographs":[
      {
        "title": "Boat Ramp"
      },
       {
        "title": "Security Camera"
      },
       {
        "title": "Exhaust Vents"
      },
       {
        "title": "Factory 1"
      },
       {
        "title": "Factory 2"
      },
       {
        "title": "Exhaust Vents"
      },
       {
        "title": "Viaduct"
      },
       {
        "title": "Girders"
      },
       {
        "title": "Office"
      }
    ]
  }
]

I am decoding it to a hash using:

galleries = ActiveSupport::JSON.decode(File.read('db/seed/galleries.json'))

I would like to get hold of an array containing all photographs in the document.

It is possible the structure of this file may change, so I would like an answer that searches on the attribute name, not its location within the hash.

What is the simplest way of getting an array containing all photographs in all galleries that does not rely on the location of the photographs within the document?

Upvotes: 0

Views: 560

Answers (1)

rossta
rossta

Reputation: 11494

You would need to write your own method to recursively search the decoded JSON structure for the key value. The method would need to decide how to handle an array, hash or string at each level of the json tree. Possibly something like this, which makes some assumptions about your data:

module KeyFinder
  def find_by_key(object, key)
    case object
    when Array
      object.each do |v|
        result = find_by_key(v, key)
        return result unless result.nil?
      end
    when Hash
      object.each do |k, v|
        if k == key
          return v
        else
          result = find_by_key(v, key)
          return result unless result.nil?
        end
      end
    else # String
      nil
    end
  end
end

include KeyFinder

find_by_key(galleries, "photographs")
# => [{"title"=>"Boat Ramp"}, {"title"=>"Security Camera"}, {"title"=>"Exhaust Vents"}, {"title"=>"Factory 1"}, {"title"=>"Factory 2"}, {"title"=>"Exhaust Vents"}, {"title"=>"Viaduct"}, {"title"=>"Girders"}, {"title"=>"Office"}]

Upvotes: 1

Related Questions