Right now, I have a server call kicking back the following Ruby hash:
{
"id"=>"-ct",
"factualId"=>"",
"outOfBusiness"=>false,
"publishedAt"=>"2012-03-09 11:02:01",
"general"=>{
"name"=>"A Cote",
"timeZone"=>"EST",
"desc"=>"À Côté is a small-plates restaurant in Oakland's charming
Rockridge district. Cozy tables surround large communal tables in both
the main dining room and on the sunny patio to create a festive atmosphere.
Small plates reflecting the best of seasonal Mediterranean cuisine are served
family-style by a friendly and knowledgeable staff.\nMenu items are paired with
a carefully chosen selection of over 40 wines by the glass as well as a highly
diverse bottled wine menu. Specialty drinks featuring fresh fruits, rare
botaniques and fine liqueurs are featured at the bar.",
"website"=>"http://acoterestaurant.com/"
},
"location"=>{
"address1"=>"5478 College Ave",
"address2"=>"",
"city"=>"Oakland",
"region"=>"CA",
"country"=>"US",
"postcode"=>"94618",
"longitude"=>37.84235,
"latitude"=>-122.25222
},
"phones"=>{
"main"=>"510-655-6469",
"fax"=>nil
},
"hours"=>{
"mon"=>{"start"=>"", "end"=>""},
"tue"=>{"start"=>"", "end"=>""},
"wed"=>{"start"=>"", "end"=>""},
"thu"=>{"start"=>"", "end"=>""},
"fri"=>{"start"=>"", "end"=>""},
"sat"=>{"start"=>"", "end"=>""},
"sun"=>{"start"=>"", "end"=>""},
"holidaySchedule"=>""
},
"businessType"=>"Restaurant"
}
It's got several attributes which are nested, such as:
"wed"=>{"start"=>"", "end"=>""}
I need to convert this object into a unnested hash in Ruby. Ideally, I'd like to detect if an attribute is nested, and respond accordingly, I.E. when it determines the attribute 'wed
' is nested, it pulls out its data and stores in the fields 'wed-start
' and 'wed-end
', or something similar.
Anyone have any tips on how to get started?
EDIT: the sparsify gem was released as a general solution to this problem.
Here's an implementation I worked up a couple months ago. You'll need to parse the JSON into a hash, then use Sparsify to sparse the hash.
usage:
This was originally created because we were working with storing a set of things in Mongo, which allowed us to use sparse keys (dot-separated) on updates to update some contents of a nested hash without overwriting unrelated keys.
Here's a first cut at a complete solution. I'm sure you can write it more elegantly, but this seems fairly clear. If you save this in a Ruby file and run it, you'll get the output I show below.
Output:
Another way to tackle this is not to flatten the hash, but to access it as though it were flattened. For example, given this hash:
then this function:
Will let you retrieve nested hash elements by concatenating the individual hash keys together with KEY_SEPARATOR (set to dash here, but could be any character that never appears as a key in the hash you need to search):
If you give a partially qualified key, you get the hash that matched at that point:
And if you give a key that doesn't exist, you get nil:
This could be monkey-patched onto Hash, if desired, by simply enclosing the above code in class Hash, and by giving self as the default to argument hash:
One more option: