I'm new to ruby and json so probably going about this in the wrong way.
I want to take an inventory which is in a pipe delimited format and convert it to json.
I had tried the example here Convert csv to json in ruby
But I am getting a bit tied up in knots with the logic as the data is in a flat format that will be converted to nested where values in the column match, for example the csv file will look like:-
id|shelf|package|price
cupboarda|shelf1|can1|10
cupboarda|shelf1|box1|20
cupboarda|shelf2|can1|10
cupboarda|shelf2|box1|20
cupboarda|shelf3|can1|30
Which I am trying to convert into a json like:-
{
"id": "cupboarda",
"shelf": {
"shelf1": {
"package": {
"can1": {
"price": "10"
},
"box1": {
"price": "20"
}
}
},
"shelf2": {
"package": {
"can1": {
"price": "10"
},
"box1": {
"price": "20"
}
}
},
"shelf3": {
"package": {
"can1": {
"price": "30"
}
}
}
}
}
I think I am on the right track with the example in the link but just getting a bit stuck with how I nest it.
This is what I tried as a way of getting everything into a kind of block so I could then figure out some logic that would extract the fields into either a nested JSON or a nested hash that I could then format as json or something else.
require 'csv'
csv_data = CSV.read 'data.csv', :col_sep => "|"
headers = csv_data.shift.map {|i| i.to_s }
string_data = csv_data.map {|row| row.map {|cell| cell.to_s } }
array_of_hashes = string_data.map {|row| Hash[*headers.zip(row).flatten] }
puts "Array"
p array_of_hashes
What's tying me up in knots is trying to figure out how to use the values from the id and start to slit and nest the data under each other. Just starting with Ruby so the logic part is my brick wall, the above code is something I found elsewhere which I thought gave me what I wanted but might not be the best approach.
Update>
Still trying to wrap my head around the logic of this but so far this is how far I have gotten:-
require 'csv'
require 'json'
csv_data = CSV.read 'inv.csv', :col_sep => "|"
headers = csv_data.shift.map {|i| i.to_s }
string_data = csv_data.map {|row| row.map {|cell| cell.to_s } }
array_of_hashes = string_data.map {|row| Hash[*headers.zip(row).flatten] }
summary = {}
array_of_hashes.each do |rec|
ida, shelfa, packagea, pricea = rec.values_at('id','shelf','package','price')
((summary[ida] ||= {})[shelfa] ||= {})[packagea] ||= 0
summary[ida][shelfa][packagea] = pricea
end
puts summary.to_json
puts summary
produces something close to what I want if I put the data in a file called inv.csv.
I get this output
{"cupboarda":{"shelf1":{"can1":"10","box1":"20"},"shelf2":{"can1":"10","box1":"20"},"shelf3":{"can1":"30"}}}
{"cupboarda"=>{"shelf1"=>{"can1"=>"10", "box1"=>"20"}, "shelf2"=>{"can1"=>"10", "box1"=>"20"}, "shelf3"=>{"can1"=>"30"}}}
I just need to figure out who I can make it compact like:-
{"cupboard":"cupboarda","shelf":{"shelf1":{"package":{"can1":{"price":"10"},"box1":{"price":"20"}}},"shelf2":{"package":{"can1":{"price":"10"},"box1":{"price":"20"}}},"shelf3":{"package":{"can1":{"price":"30"}}}}}