19

Does anyone know how to write a Ruby script that would convert a csv file to a json file?

The CSV would be in this format:

Canon,Digital IXUS 70,"Epic, Epic 100",3x,Yes (lockable),Yes (lockable),Yes
Canon, Digital IXUS 75,"Epic, Epic 100",3x,Yes (lockable),Yes (lockable),Yes
Canon,Digital IXUS 80,"Epic, Epic 100",3x,Yes (lockable),Yes (lockable),Yes

and the JSON would need to result in this:

{ "aaData": [
[ "Canon" , "Digital IXUS 70" , "3x" , "Yes (lockable)" , "Yes (lockable)" , "Yes"],
[ "Canon" , "Digital IXUS 75" , "3x" , "Yes (lockable)" , "Yes (lockable)" , "Yes"],
[ "Canon" , "Digital IXUS 80" , "3x" , "Yes (lockable)" , "Yes (lockable)" , "Yes"]
]} 

5 Answers 5

49

This is easy in ruby 1.9 where data is your csv data string

 require 'csv'
 require 'json'

 CSV.parse(data).to_json
Sign up to request clarification or add additional context in comments.

3 Comments

thanks doesn't work for 1.8 and i can't upgrade- what is the correct syntax for 1.87?
Install gem 'fastercsv' and change CSV to FasterCSV
data = File.open('/path/to/file.csv').read to assign data
29

To go from:

Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00

To

[
  {:year => 1997, :make => 'Ford', :model => 'E350', :description => 'ac, abs, moon', :price => 3000.00},
  {:year => 1999, :make => 'Chevy', :model => 'Venture "Extended Edition"', :description => nil, :price => 4900.00},
  {:year => 1999, :make => 'Chevy', :model => 'Venture "Extended Edition, Very Large"', :description => nil, :price => 5000.00},
  {:year => 1996, :make => 'Jeep', :model => 'Grand Cherokee', :description => "MUST SELL!\nair, moon roof, loaded", :price => 4799.00}
]

Do this:

csv = CSV.new(body, :headers => true, :header_converters => :symbol, :converters => :all)
csv.to_a.map {|row| row.to_hash }
#=> [{:year=>1997, :make=>"Ford", :model=>"E350", :description=>"ac, abs, moon", :price=>3000.0}, {:year=>1999, :make=>"Chevy", :model=>"Venture \"Extended Edition\"", :description=>"", :price=>4900.0}, {:year=>1999, :make=>"Chevy", :model=>"Venture \"Extended Edition, Very Large\"", :description=>nil, :price=>5000.0}, {:year=>1996, :make=>"Jeep", :model=>"Grand Cherokee", :description=>"MUST SELL!\nair, moon roof, loaded", :price=>4799.0}]

Credit: https://technicalpickles.com/posts/parsing-csv-with-ruby

Comments

15

Building on Josh's example, you can now take it one step further using CSV::table:

extracted_data   = CSV.table('your/file.csv')
transformed_data = extracted_data.map { |row| row.to_hash }

Now you can call to_json to use it right away, or write it down to a file, nicely formatted:

File.open('your/file.json', 'w') do |file|
  file.puts JSON.pretty_generate(transformed_data)
end

1 Comment

extracted_data = CSV.table('your/file.csv', header_converters: nil) if you want to keep the headers as the original strings, rather than camelizing and converting to symbols
9

If you're in a Rails project

CSV.parse(csv_string, {headers: true})
csv.map(&:to_h).to_json

1 Comment

Works fine in plain Ruby as well: ruby -e "require 'csv'; require 'json'" -e "puts CSV.parse(File.open(ARGV[0]), {headers: true}).map(&:to_h).to_json" example.csv
2

My solution ended up this way, quite similar to Mariu's

require 'csv'
require 'json'

csv_table = CSV.parse(File.read('data.csv'), headers: true)
json_string = csv_table.map(&:to_h).to_json

File.open('data.json','w') do |f|
  f.puts(json_string)
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.