0

Let's say I have a mapping of how I want a hash to turn out, along with new key names like this:

JSON_MAP = {
  image: {
    id: :id,
    media_url: :url,
    time: :duration,
    timestamp: :time_posted,
    text_caption: :caption,
    metadata: {
      camera: :camera_type,
      flash: :camera_flash
    }
  },
  viewers: {
    views: :view_count,
    likes: :likes_count
  }
}

and I have a hash like this:

{
  image: {
    id: 1,
    media_url: 'http://placekitten.com',
    nsfw: false,
    time: 4,
    timestamp: 14149292,
    text_caption: "I'm a kitten",
    metadata: {
      camera: 'iPhone',
      flash: true
    }
  },
  viewers: {
    views: 50,
    likes: 15
  },
  extras: {
    features: {
      enabled: true
    }
  }
}

I only want it to transform the data so it ends up like:

{
  image: {
    id: 1,
    url: 'http://placekitten.com',
    duration: 4,
    time_posted: 14149292,
    caption: "I'm a kitten",
    metadata: {
      camera: 'iPhone',
      flash: true
    }
  },
  viewers: {
    view_count: 50,
    likes_count: 15
  }
}

Basically, renaming all the keys based on the source map, and deleting any keys that don't match the source map...

1

1 Answer 1

1

You can obtain your desired result using recursion.

def convert(mapper, hsh)
  mapper.each_with_object({}) do |(k,o),h|
    next unless hsh.key?(k)
    if o.is_a? Hash
      h[k] = convert(o, hsh[k])
    else
      h[o] = hsh[k]
    end
  end
end

Assuming h equals your second hash,

convert(JSON_MAP, h)    
  #=> { :image=>{
  #       :id=>1,
  #       :url=>"http://placekitten.com",
  #       :duration=>4,
  #       :time_posted=>14149292,
  #       :caption=>"I'm a kitten",
  #       :metadata=>{
  #         :camera_type=>"iPhone",
  #         :camera_flash=>true
  #       }
  #     },
  #     :viewers=>{
  #       :view_count=>50,
  #       :likes_count=>15
  #     }
  #   } 
Sign up to request clarification or add additional context in comments.

5 Comments

Hrm, that didn't work for me - saying "recurse" is not a method?
I initially had two methods: convert and recurse, then realized I only needed one, convert, but I forgot to change recurse to convert in the body. I've made the correction.
Please elaborate. The method works fine for the two hashes in your question.
Ah I found that it fails if a hash isn't there.. so if metadata didn't exist, it failed.
Good catch. It would also fail if there were no key :image or :viewers. Your fix seems to cover all those cases.

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.