Reputation: 476
I have an array of nested JSON "hash" objects that I need to completely flatten so it ports over to CSV cleanly, which is obviously not nested and "multidimensional" like JSON typically is.
But the flatten method (used here with ! bang) is not working (it creates the file with no error but then the file is empty).
In my ruby file below I leave a working example of commented out code which isjust doing a simply conversion without the .flatten method. Since the JSON is an array (at the highest level) - separated by commas and enclosed in square brackets, shouldn't it take the .flatten method, just as it takes .each in the working commented out block? (This is also what the docs seems to indicate!)
require 'csv'
require 'json'
# CSV.open('false-hotels-merged.csv', 'w') do |csv|
# JSON.parse(File.open('monfri-false-hotels-merged.json').read).each do |hash|
# csv << hash.values
# end
# end
CSV.open('wed-all-false-hotels.csv', 'w') do |csv|
JSON.parse(File.open('monfri-false-hotels-merged.json').read).flatten! do |f|
csv << f.values
end
end
Example JSON data snippet:
[...
{
"id": "111707",
"name": "Seven Park Place by William Drabble",
"phone": "+442073161600",
"email": "[email protected]",
"website": "http://www.stjameshotelandclub.com/michelin-star-chef-william-drabble",
"location": {
"latitude": 51.5062548,
"longitude": -0.1403209,
"address": {
"line1": "7-8 Park Place",
"line2": "St James's",
"line3": "",
"postcode": "SW1A 1LP",
"city": "London",
"country": "UK"
}
}
},
{
"id": "104493",
"name": "Seymour's Restaurant & Bar",
"phone": "+442079352010",
"email": "[email protected]",
"website": "http://www.theleonard.com",
"location": {
"latitude": 51.51463,
"longitude": -0.15779,
"address": {
"line1": "15 Seymour Street",
"line2": "",
"line3": "",
"postcode": "W1H 7JW",
"city": "London",
"country": "UK"
}
}
},
{
"id": "250922",
"name": "Shaka Zulu",
"phone": "+442033769911",
"email": "[email protected]",
"website": "http://www.shaka-zulu.com/",
"location": {
"latitude": 51.5414979,
"longitude": -0.1458655,
"address": {
"line1": "Stables Market ",
"line2": "Camden",
"line3": "",
"postcode": "NW1 8AB",
"city": "London",
"country": "UK"
}
}
}
]
Again, no errors at all in the terminal - just blank CSV file created.
Upvotes: 0
Views: 654
Reputation: 2883
Try this:
require 'csv'
require 'json'
def hflat(h)
h.values.flat_map {|v| v.is_a?(Hash) ? hflat(v) : v }
end
CSV.open('file.csv', 'w') do |csv|
JSON.parse(File.open('file.json').read).each do |h|
csv << hflat(h)
end
end
Upvotes: 1
Reputation: 2337
Array#flatten
only flattens arrays. There is also Hash#flatten
, which also produces an array. You seem to want to flatten a nested Hash for which I don't know of a library method.
It seems that your result is empty because there's an .each
missing after the flatten
- the block is simply not run.
Upvotes: 3