1

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"}}}}}
Community
  • 1
  • 1
Steve
  • 11
  • 3
  • Show your efforts please. – Roman Kiselenko May 18 '16 at 10:26
  • What exactly have you tried? Please post your actual code. – Tom Lord May 18 '16 at 10:31
  • First I tried the example in the link. then I tried this example to convert it into an array of hashes `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` then I planned to extract some uniq values to perform some searches with to produce the nested output `cupboard = array_of_hashes.map { |h| h["cupboard"] }.uniq ` – Steve May 18 '16 at 12:43
  • @Steve As you can see, code isn't very readable in comments. It's ok, and even preferred, to put the code you tried in the question itself. You can click 'Edit' on your question and add it, explaining that this is what you tried so far. – Keith Bennett May 18 '16 at 14:57

1 Answers1

-2

What language are you using?

For javascript look up "jsfiddle csv json" in Google and for c# take a look at this question. In my c# project I make use of NewtonSoft's brilliant JSON framework.

Community
  • 1
  • 1
err1
  • 499
  • 9
  • 22
  • Have you read the title of question ? _Convert CSV to a nested **Ruby** hash/JSON_, this question also tagged as ruby. – Roman Kiselenko May 18 '16 at 10:39
  • OK, why has my answer been voted down? He didn't specify the lanuage that he was using and I gave him some general pointers. And if YOU care to read or follow the links.... – err1 May 18 '16 at 10:40
  • trying to do it in ruby – Steve May 18 '16 at 12:48