module ObjectTraverser

def extract_from_array(key, value)

Otherwise, support methods on the Array itself.
If the values to return from is an Array, allow returning by index.
def extract_from_array(key, value)
  if key.is_a?(Integer)
    value[key]
  elsif value.respond_to?(key.to_sym)
    value.send(key.to_sym)
  end
end

def extract_from_hash(key, value)

This will return nil default if we can't find the key.

if the keys themselves are symbols, for example.
We first try to find by the raw key before we stringify
for Hashes, try to return the value by the key.
def extract_from_hash(key, value)
  if value.key?(key)
    value[key]
  elsif value.key?(key.to_s)
    value[key.to_s]
  end
end

def extract_value(keys, value)

def extract_value(keys, value)
  return nil if value.nil?
  key = keys.shift
  return nil if key.nil?
  # if the current value is not a Hash or Array, it is undefined
  # behavior so value will be assigned nil by default.
  value = if value.is_a?(Array)
            extract_from_array(key, value)
          elsif value.is_a?(Hash)
            extract_from_hash(key, value)
          end
  # if there are no more keys, just return the value
  return value if keys.first.nil?
  # if there are more keys, extract more
  extract_value(keys.clone, value)
end