whoopee-cushion

Imagine the scene. You're accessing a nice JSON API, but the data you get back is difficult to work with. There are a number of reasons why this is, but mainly it's because you're dealing with a giant hash, using camel case for keys.

It all leads to ugly, unreadable Ruby code like this:

obj['Products'].first['Customer']['CustomerId']

Wouldn't it be nice if you could access all your API response data like this?

obj.products.first.customer.customer_id

whoopee-cushion will let you do just that. It's faster than using OpenStructs and any recursive algorithms based on them because it uses Ruby's faster Struct objects under the hood.

Setup

gem install whoopee-cushion

or

gem "whoopee-cushion"

in your Gemfile.

In your Ruby code:

require 'whoopee_cushion'

then

hash = {:a => 1, :CamelCase => 2, :c => 3, :d => { :e => 4, :f => [1,2,3,4,5]}}

obj = WhoopeeCushion::Inflate.from_hash(hash)

puts obj.a

puts obj.camel_case

puts obj.d.f.first

You can also go straight from JSON, or turn off the automatic camel case conversion:

json = '{"CamelCase": "no", "json": "yes"}'

obj = WhoopeeCushion::Inflate.from_json(json, :convert_keys => false)

puts obj.CamelCase

If you want to carry out your own string conversion, use a lambda:

hash = {:a => 1, :CamelCase => 2, :c => 3, :d => { :e => 4, :f => [1,2,3,4,5]}}

obj = WhoopeeCushion::Inflate.from_hash(hash, :convert_keys => lambda {|s| '#{s}_foo'})

puts obj.a_foo

puts obj.CamelCase_foo

puts obj.d_foo.f_foo.first

Performance

Check the project out, bundle it and run the simple rake benchmark suite to see some figures. Comparisons are made against the recursive-open-struct gem and simple OpenStruct creates. The whoopee-cushion gem performs very well against both when not converting strings to snake case (quite an expensive operation, using a stripped-down version of the Rails 'underscore' method.) When converting strings the performance increase is diminished, but it still comes out well.

If you can increase performance (or otherwise improve the gem in any way) please fork it and issue a pull request.